PWebUtil.getAuthKey = function() {
	scripts = document.getElementsByTagName("script");
	for (i = 0; i < scripts.length; i++) {
		reg = /(auth|js|api\.js\.jsp)\?key=(.+)/;
		if (match = reg.exec(scripts[i].src)) {
			// remove other params
			var tokens = match[2].split("&");
			k = tokens ? tokens[0] : tokens;
			return k;
		}
	}
	return null;
}

/******************************************************************************
 * This file has been modified by Piergiorgio Navone 
 *
 * $Id: excanvas.js,v 1.1 2006/05/31 11:09:08 pspencer Exp $
 *****************************************************************************/

// Copyright 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// TODO: Patterns
// TODO: Radial gradient
// TODO: Clipping paths
// TODO: Coordsize
// TODO: Painting mode
// TODO: Optimize
// TODO: canvas width/height sets content size in moz, border size in ie
// TODO: Painting outside the canvas should not be allowed

// only add this code if we do not already have a canvas implementation

// TJM - 05/24/10 - commented out based on discussion with Almog related to non-trasparent polygons in IE8 for Miami
 if (1) {
//if (!window.CanvasRenderingContext2D) {
(function () {
  var G_vmlCanvasManager_ = {
    init: function (opt_doc) {
      var doc = opt_doc || document;
      if (/MSIE/.test(navigator.userAgent) && !window.opera) {
        var self = this;
        doc.attachEvent("onreadystatechange", function () {
          self.init_(doc);
        });
      }
    },

    init_: function (doc, e) {
      if (doc.readyState == "complete") {
        // create xmlns
        if (!doc.namespaces["g_vml_"]) {
          doc.namespaces.add("g_vml_", "urn:schemas-microsoft-com:vml");
        }

        // setup default css
        var ss = doc.createStyleSheet();
        ss.cssText = "canvas{display:inline-block;overflow:hidden;" + "text-align:left;}" + "g_vml_\\:*{behavior:url(#default#VML)}";
//        ss.cssText = "canvas{display:inline-block;" +  "text-align:left;}" +  "canvas *{behavior:url(#default#VML)}";

        // find all canvas elements
        var els = doc.getElementsByTagName("canvas");
        for (var i = 0; i < els.length; i++) {
          if (!els[i].getContext) {
            this.initElement(els[i]);
          }
        }
      }
    },

    fixElement_: function (el) {
      // in IE before version 5.5 we would need to add HTML: to the tag name
      // but we do not care about IE before version 6
      var outerHTML = el.outerHTML;
      var newEl = document.createElement(outerHTML);
      // if the tag is still open IE has created the children as siblings and
      // it has also created a tag with the name "/FOO"
      if (outerHTML.slice(-2) != "/>") {
        var tagName = "/" + el.tagName;
        var ns;
        // remove content
        while ((ns = el.nextSibling) && ns.tagName != tagName) {
          ns.removeNode();
        }
        // remove the incorrect closing tag
        if (ns) {
          ns.removeNode();
        }
      }
      el.parentNode.replaceChild(newEl, el);
      return newEl;
    },

    //
    // Public initializes a canvas element so that it can be used as canvas
    //element from now on. This is called automatically before the page is
    //loaded but if you are creating elements using createElement yuo need to
    // make sure this is called on the element.
    //@param el {HTMLElement} The canvas element to initialize.
    //
    initElement: function (el) {
      el = this.fixElement_(el);
      el.getContext = function () {
        if (this.context_) {
          this.context_.m_ = createMatrixIdentity();
          return this.context_;
        }
        return this.context_ = new CanvasRenderingContext2D_(this);
      };

      var self = this; //bind
      el.attachEvent("onpropertychange", function (e) {
        // we need to watch changes to width and height
        switch (e.propertyName) {
          case "width":
          case "height":
            // coord size changed?
            break;
        }
      });

      // if style.height is set

      var attrs = el.attributes;
      if (attrs.width && attrs.width.specified) {
        // TODO: use runtimeStyle and coordsize
        // el.getContext().setWidth_(attrs.width.nodeValue);
        el.style.width = attrs.width.nodeValue + "px";
      }
      if (attrs.height && attrs.height.specified) {
        // TODO: use runtimeStyle and coordsize
        // el.getContext().setHeight_(attrs.height.nodeValue);
        el.style.height = attrs.height.nodeValue + "px";
      }
      //el.getContext().setCoordsize_()
      
      return el;
    }
  };

  G_vmlCanvasManager_.init();

  // precompute "00" to "FF"
  var dec2hex = [];
  for (var i = 0; i < 16; i++) {
    for (var j = 0; j < 16; j++) {
      dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
    }
  }

  function createMatrixIdentity() {
    return [
      [1, 0, 0],
      [0, 1, 0],
      [0, 0, 1]
    ];
  }

  function matrixMultiply(m1, m2) {
    var result = createMatrixIdentity();

    for (var x = 0; x < 3; x++) {
      for (var y = 0; y < 3; y++) {
        var sum = 0;

        for (var z = 0; z < 3; z++) {
          sum += m1[x][z] * m2[z][y];
        }

        result[x][y] = sum;
      }
    }
    return result;
  }

  function copyState(o1, o2) {
    o2.fillStyle     = o1.fillStyle;
    o2.lineCap       = o1.lineCap;
    o2.lineJoin      = o1.lineJoin;
    o2.lineWidth     = o1.lineWidth;
    o2.miterLimit    = o1.miterLimit;
    o2.shadowBlur    = o1.shadowBlur;
    o2.shadowColor   = o1.shadowColor;
    o2.shadowOffsetX = o1.shadowOffsetX;
    o2.shadowOffsetY = o1.shadowOffsetY;
    o2.strokeStyle   = o1.strokeStyle;
  }

  function processStyle(styleString) {
    var str, alpha = 1;

    styleString = String(styleString);
    if (styleString.substring(0, 3) == "rgb") {
      var start = styleString.indexOf("(", 3);
      var end = styleString.indexOf(")", start + 1);
      var guts = styleString.substring(start + 1, end).split(",");

      str = "#";
      for (var i = 0; i < 3; i++) {
        str += dec2hex[parseInt(guts[i])];
      }

      if ((guts.length == 4) && (styleString.substr(3, 1) == "a")) {
        alpha = guts[3];
      }
    } else {
      str = styleString;
    }

    return [str, alpha];
  }

  function processLineCap(lineCap) {
    switch (lineCap) {
      case "butt":
        return "flat";
      case "round":
        return "round";
      case "square":
      default:
        return "square";
    }
  }

  //
   // This class implements CanvasRenderingContext2D interface as described by
   //the WHATWG.
   // @param surfaceElement {HTMLElement} The element that the 2D context should
   //be associated with
   //
   function CanvasRenderingContext2D_(surfaceElement) {
    this.m_ = createMatrixIdentity();
    this.element_ = surfaceElement;

    this.mStack_ = [];
    this.aStack_ = [];
    this.currentPath_ = [];

    // Canvas context properties
    this.strokeStyle = "#000";
    this.fillStyle = "#ccc";

    this.lineWidth = 1;
    this.lineJoin = "miter";
    this.lineCap = "butt";
    this.miterLimit = 10;
    this.globalAlpha = 1;
  };

  var contextPrototype = CanvasRenderingContext2D_.prototype;
  contextPrototype.clearRect = function() {
    this.element_.innerHTML = "";
    this.currentPath_ = [];
  };

  contextPrototype.beginPath = function() {
    // TODO: Branch current matrix so that save/restore has no effect
    //       as per safari docs.

    this.currentPath_ = [];
  };

  contextPrototype.moveTo = function(aX, aY) {
    this.currentPath_.push({type: "moveTo", x: aX, y: aY});
  };

  contextPrototype.lineTo = function(aX, aY) {
    this.currentPath_.push({type: "lineTo", x: aX, y: aY});
  };

  contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
                                            aCP2x, aCP2y,
                                            aX, aY) {
    this.currentPath_.push({type: "bezierCurveTo",
                           cp1x: aCP1x,
                           cp1y: aCP1y,
                           cp2x: aCP2x,
                           cp2y: aCP2y,
                           x: aX,
                           y: aY});
  };

  contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
    // VML's qb produces different output to Firefox's
    // FF's behaviour seems to have changed in 1.5.0.1, check this
    this.bezierCurveTo(aCPx, aCPy, aCPx, aCPy, aX, aY);
  };

  contextPrototype.arc = function(aX, aY, aRadius,
                                  aStartAngle, aEndAngle, aClockwise) {
    if (!aClockwise) {
      var t = aStartAngle;
      aStartAngle = aEndAngle;
      aEndAngle = t;
    }

    var xStart = aX + (Math.cos(aStartAngle) * aRadius);
    var yStart = aY + (Math.sin(aStartAngle) * aRadius);

    var xEnd = aX + (Math.cos(aEndAngle) * aRadius);
    var yEnd = aY + (Math.sin(aEndAngle) * aRadius);

    this.currentPath_.push({type: "arc",
                           x: aX,
                           y: aY,
                           radius: aRadius,
                           xStart: xStart,
                           yStart: yStart,
                           xEnd: xEnd,
                           yEnd: yEnd});

  };

  contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
  };

  contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
    // Will destroy any existing path (same as FF behaviour)
    this.beginPath();
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.stroke();
  };

  contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
    // Will destroy any existing path (same as FF behaviour)
    this.beginPath();
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.fill();
  };

  contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
    var gradient = new CanvasGradient_("gradient");
    return gradient;
  };

  contextPrototype.createRadialGradient = function(aX0, aY0,
                                                   aR0, aX1,
                                                   aY1, aR1) {
    var gradient = new CanvasGradient_("gradientradial");
    gradient.radius1_ = aR0;
    gradient.radius2_ = aR1;
    gradient.focus_.x = aX0;
    gradient.focus_.y = aY0;
    return gradient;
  };

  contextPrototype.drawImage = function (image, var_args) {
    var dx, dy, dw, dh, sx, sy, sw, sh;
    var w = image.width;
    var h = image.height;

    if (arguments.length == 3) {
      dx = arguments[1];
      dy = arguments[2];
      sx = sy = 0;
      sw = dw = w;
      sh = dh = h;
    } else if (arguments.length == 5) {
      dx = arguments[1];
      dy = arguments[2];
      dw = arguments[3];
      dh = arguments[4];
      sx = sy = 0;
      sw = w;
      sh = h;
    } else if (arguments.length == 9) {
      sx = arguments[1];
      sy = arguments[2];
      sw = arguments[3];
      sh = arguments[4];
      dx = arguments[5];
      dy = arguments[6];
      dw = arguments[7];
      dh = arguments[8];
    } else {
      throw "Invalid number of arguments";
    }

    var d = this.getCoords_(dx, dy);

    var w2 = (sw / 2);
    var h2 = (sh / 2);

    var vmlStr = [];

    // For some reason that I've now forgotten, using divs didn't work
    vmlStr.push(' <g_vml_:group',
                ' coordsize="100,100"',
                ' coordorigin="0, 0"' ,
                ' style="width:100px;height:100px;position:absolute;');

    // If filters are necessary (rotation exists), create them
    // filters are bog-slow, so only create them if abbsolutely necessary
    // The following check doesn't account for skews (which don't exist
    // in the canvas spec (yet) anyway.

    if (this.m_[0][0] != 1 || this.m_[0][1]) {
      var filter = [];

      // Note the 12/21 reversal
      filter.push("M11='", this.m_[0][0], "',",
                  "M12='", this.m_[1][0], "',",
                  "M21='", this.m_[0][1], "',",
                  "M22='", this.m_[1][1], "',",
                  "Dx='", d.x, "',",
                  "Dy='", d.y, "'");

      // Bounding box calculation (need to minimize displayed area so that
      // filters don't waste time on unused pixels.
      var max = d;
      var c2 = this.getCoords_(dx+dw, dy);
      var c3 = this.getCoords_(dx, dy+dh);
      var c4 = this.getCoords_(dx+dw, dy+dh);

      max.x = Math.max(max.x, c2.x, c3.x, c4.x);
      max.y = Math.max(max.y, c2.y, c3.y, c4.y);

      vmlStr.push(" padding:0 ", Math.floor(max.x), "px ", Math.floor(max.y),
                  "px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",
                  filter.join(""), ", sizingmethod='clip');")
    } else {
      vmlStr.push(" top:", d.y, "px;left:", d.x, "px;")
    }

    vmlStr.push(' ">' ,
                '<g_vml_:image src="', image.src, '"',
                ' style="width:', dw, ';',
                ' height:', dh, ';"',
                ' cropleft="', sx / w, '"',
                ' croptop="', sy / h, '"',
                ' cropright="', (w - sx - sw) / w, '"',
                ' cropbottom="', (h - sy - sh) / h, '"',
                ' />',
                '</g_vml_:group>');

    this.element_.insertAdjacentHTML("BeforeEnd",
                                    vmlStr.join(""));
  };

  contextPrototype.stroke = function(aFill) {
    var lineStr = [];
    var lineOpen = false;
    var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
    var color = a[0];
    var opacity = a[1] * this.globalAlpha;

    lineStr.push('<g_vml_:shape',
                 ' fillcolor="', color, '"',
                 ' filled="', Boolean(aFill), '"',
                 ' style="position:absolute;width:10;height:10;"',
                 ' coordorigin="0 0" coordsize="10 10"',
                 ' stroked="', !aFill, '"',
                 ' strokeweight="', this.lineWidth, '"',
                 ' strokecolor="', color, '"',
                 ' path="');

    var newSeq = false;
    var min = {x: null, y: null};
    var max = {x: null, y: null};

    for (var i = 0; i < this.currentPath_.length; i++) {
      var p = this.currentPath_[i];

      if (p.type == "moveTo") {
        lineStr.push(" m ");
        var c = this.getCoords_(p.x, p.y);
        lineStr.push(Math.floor(c.x), ",", Math.floor(c.y));
      } else if (p.type == "lineTo") {
        lineStr.push(" l ");
        var c = this.getCoords_(p.x, p.y);
        lineStr.push(Math.floor(c.x), ",", Math.floor(c.y));
      } else if (p.type == "close") {
        lineStr.push(" x ");
      } else if (p.type == "bezierCurveTo") {
        lineStr.push(" c ");
        var c = this.getCoords_(p.x, p.y);
        var c1 = this.getCoords_(p.cp1x, p.cp1y);
        var c2 = this.getCoords_(p.cp2x, p.cp2y);
        lineStr.push(Math.floor(c1.x), ",", Math.floor(c1.y), ",",
                     Math.floor(c2.x), ",", Math.floor(c2.y), ",",
                     Math.floor(c.x), ",", Math.floor(c.y));
      } else if (p.type == "arc") {
        lineStr.push(" ar ");
        var c  = this.getCoords_(p.x, p.y);
        var cStart = this.getCoords_(p.xStart, p.yStart);
        var cEnd = this.getCoords_(p.xEnd, p.yEnd);

        // TODO: FIX (matricies (scale+rotation) now buggered this up)
        //       VML arc also doesn't seem able to do rotated non-circular
        //       arcs without parent grouping.
        var absXScale = this.m_[0][0];
        var absYScale = this.m_[1][1];

        lineStr.push(Math.floor(c.x - absXScale * p.radius), ",",
                     Math.floor(c.y - absYScale * p.radius), " ",
                     Math.floor(c.x + absXScale * p.radius), ",",
                     Math.floor(c.y + absYScale * p.radius), " ",
                     Math.floor(cStart.x), ",", Math.floor(cStart.y), " ",
                     Math.floor(cEnd.x), ",", Math.floor(cEnd.y));
      }


      // TODO: Following is broken for curves due to
      //       move to proper paths.

      // Figure out dimensions so we can do gradient fills
      // properly
      if(c) {
        if (min.x == null || c.x < min.x) {
          min.x = c.x;
        }
        if (max.x == null || c.x > max.x) {
          max.x = c.x;
        }
        if (min.y == null || c.y < min.y) {
          min.y = c.y;
        }
        if (max.y == null || c.y > max.y) {
          max.y = c.y;
        }
      }
    }
    lineStr.push(' ">');

    if (typeof this.fillStyle == "object") {
      var focus = {x: "50%", y: "50%"};
      var width = (max.x - min.x);
      var height = (max.y - min.y);
      var dimension = (width > height) ? width : height;

      focus.x = Math.floor((this.fillStyle.focus_.x / width) * 100 + 50) + "%";
      focus.y = Math.floor((this.fillStyle.focus_.y / height) * 100 + 50) + "%";

      var colors = [];

      // inside radius (%)
      if (this.fillStyle.type_ == "gradientradial") {
        var inside = (this.fillStyle.radius1_ / dimension * 100);

        // percentage that outside radius exceeds inside radius
        var expansion = (this.fillStyle.radius2_ / dimension * 100) - inside;
      } else {
        var inside = 0;
        var expansion = 100;
      }

      var insidecolor = {offset: null, color: null};
      var outsidecolor = {offset: null, color: null};

      // We need to sort 'colors' by percentage, from 0 > 100 otherwise ie
      // won't interpret it correctly
      this.fillStyle.colors_.sort(function (cs1, cs2) {
        return cs1.offset - cs2.offset;
      });

      for (var i = 0; i < this.fillStyle.colors_.length; i++) {
        var fs = this.fillStyle.colors_[i];

        colors.push( (fs.offset * expansion) + inside, "% ", fs.color, ",");

        if (fs.offset > insidecolor.offset || insidecolor.offset == null) {
          insidecolor.offset = fs.offset;
          insidecolor.color = fs.color;
        }

        if (fs.offset < outsidecolor.offset || outsidecolor.offset == null) {
          outsidecolor.offset = fs.offset;
          outsidecolor.color = fs.color;
        }
      }
      colors.pop();

      lineStr.push('<g_vml_:fill',
                   ' color="', outsidecolor.color, '"',
                   ' color2="', insidecolor.color, '"',
                   ' type="', this.fillStyle.type_, '"',
                   ' focusposition="', focus.x, ', ', focus.y, '"',
                   ' colors="', colors.join(""), '"',
                   ' opacity="', opacity, '" />');
    } else if (aFill) {
      lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity, '" />');
    } else {
      lineStr.push(
        '<g_vml_:stroke',
        ' opacity="', opacity,'"',
        ' joinstyle="', this.lineJoin, '"',
        ' miterlimit="', this.miterLimit, '"',
        ' endcap="', processLineCap(this.lineCap) ,'"',
        ' weight="', this.lineWidth, 'px"',
        ' color="', color,'" />'
      );
    }

    lineStr.push("</g_vml_:shape>");

    this.element_.insertAdjacentHTML("beforeEnd", lineStr.join(""));

    //this.currentPath_ = [];
  };

  contextPrototype.fill = function() {
    this.stroke(true);
  }

  contextPrototype.closePath = function() {
    this.currentPath_.push({type: "close"});
  };

  //
  // @private
  //
  contextPrototype.getCoords_ = function(aX, aY) {
    return {
      x: (aX * this.m_[0][0] + aY * this.m_[1][0] + this.m_[2][0]),
      y: (aX * this.m_[0][1] + aY * this.m_[1][1] + this.m_[2][1])
    }
  };

  contextPrototype.save = function() {
    var o = {};
    copyState(this, o);
    this.aStack_.push(o);
    this.mStack_.push(this.m_);
    this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
  };

  contextPrototype.restore = function() {
    copyState(this.aStack_.pop(), this);
    this.m_ = this.mStack_.pop();
  };

  contextPrototype.translate = function(aX, aY) {
    var m1 = [
      [1,  0,  0],
      [0,  1,  0],
      [aX, aY, 1]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  contextPrototype.rotate = function(aRot) {
    var c = Math.cos(aRot);
    var s = Math.sin(aRot);

    var m1 = [
      [c,  s, 0],
      [-s, c, 0],
      [0,  0, 1]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  contextPrototype.scale = function(aX, aY) {
    var m1 = [
      [aX, 0,  0],
      [0,  aY, 0],
      [0,  0,  1]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  // STUBS 
  contextPrototype.clip = function() {
    // TODO: Implement
  };

  contextPrototype.arcTo = function() {
    // TODO: Implement
  };

  contextPrototype.createPattern = function() {
    return new CanvasPattern_;
  };

  // Gradient / Pattern Stubs
  function CanvasGradient_(aType) {
    this.type_ = aType;
    this.radius1_ = 0;
    this.radius2_ = 0;
    this.colors_ = [];
    this.focus_ = {x: 0, y: 0};
  }

  CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
    aColor = processStyle(aColor);
    this.colors_.push({offset: 1-aOffset, color: aColor});
  };

  function CanvasPattern_() {}

  // set up externs
  G_vmlCanvasManager = G_vmlCanvasManager_;
  CanvasRenderingContext2D = CanvasRenderingContext2D_;
  CanvasGradient = CanvasGradient_;
  CanvasPattern = CanvasPattern_;

})();

} // if


//If firefox version < 3 then use SVG rather than canvas.
// if( _BrowserIdent_browser = "Firefox" &&  _BrowserIdent_version < 3){
// TJM - 05/27/10 - bug in code, should be testing for equals, not making it equal
 if( _BrowserIdent_browser == "Firefox" &&  _BrowserIdent_version < 3){
	
	PChart.prototype.refresh = function() {
		this.clear();
	
		var labels = [];
		var data = [];
	
		// get xaxis var
		var xVar = [];
		if (this.options.xAxis == PChartOptions.PLACE)
			xVar = this.cube.places;
		else if (this.options.xAxis == PChartOptions.INDICATOR)
			xVar = this.cube.indicators;
		else
			xVar = this.cube.periods;
	
		// get grouped var
		var groupVar = [];
		if (this.options.group == PChartOptions.PLACE)
			groupVar = this.cube.places;
		else if (this.options.group == PChartOptions.INDICATOR)
			groupVar = this.cube.indicators;
		else
			groupVar = this.cube.periods;
	
		// deduce remaining var
		var rVar = [];
		if ((this.options.xAxis == PChartOptions.PLACE && this.options.group == PChartOptions.INDICATOR) || (this.options.xAxis == PChartOptions.INDICATOR && this.options.group == PChartOptions.PLACE))
			rVar = this.cube.periods;
		else if ((this.options.xAxis == PChartOptions.PLACE && this.options.group == PChartOptions.PERIOD) || (this.options.xAxis == PChartOptions.PERIOD && this.options.group == PChartOptions.PLACE))
			rVar = this.cube.indicators;
		else
			rVar = this.cube.places;
	
		// loop through x vars and label
		if (this.options.displayXAxisLabel) {
			for (var i=0; i<xVar.length; i++) {
				// set x labels
				var label = "";
				if (xVar[i] instanceof PPlace)
					label = this.getPlaceLabel(xVar[i]);
				else if (xVar[i] instanceof PIndicator)
					label = this.getIndicatorLabel(xVar[i]);
				else
					label = xVar[i];
				var xticks = {v: i, label: label};
				labels.push(xticks);
			}
		}
	
		// loop through all vars
		var periodid = null;
		var placeid = null;
		var indid = null;
		var maxValue = 0;
		for (var i=0; i<groupVar.length; i++) {
			var values = [];
			if (groupVar[i] instanceof PPlace)
				placeid = groupVar[i].id;
			else if (groupVar[i] instanceof PIndicator)
				indid = groupVar[i].id;
			else
				periodid = groupVar[i];
	
			for (var j=0; j<xVar.length; j++) {
				if (xVar[j] instanceof PPlace)
					placeid = xVar[j].id;
				else if (xVar[j] instanceof PIndicator)
					indid = xVar[j].id;
				else
					periodid = xVar[j];
	
				for (var k=0; k<rVar.length; k++) {
					if (rVar[k] instanceof PPlace)
						placeid = rVar[k].id;
					else if (rVar[k] instanceof PIndicator)
						indid = rVar[k].id;
					else
						periodid = rVar[k];
	
					var value = this.cube.values[periodid][placeid][indid];
					if (value && value > maxValue)
						maxValue = value;
					if (!value)
						value = 0;
					values.push([j, value]);
				}
			}
			data.push(values);
		}
	
		if (this.options.yMax)
			maxValue = this.options.yMax;
		else {
			var interval = "1";
			var maxInt = maxValue.toString().split(".");
			for (var i=1; i<maxInt[0].toString().length; i++)
				interval += "0";
			maxValue += parseInt(interval);
			maxValue = parseInt(maxValue / interval) * interval;
		}
	
		var intervals = this.options.yIntervals;
		if (intervals == null) {
			intervals = maxValue.toString().charAt(0);
			if (intervals < 2)
				intervals = intervals * 4;
			else if (intervals < 4)
				intervals = intervals * 2;
		}
	
		this.layoutOptions = {
		   "xTicks": labels,
		   "yAxis": [0,maxValue],
		   "yNumberOfTicks": intervals,
		   "yTickPrecision": this.options.yDecimal
		};
	
		var hexColor = MochiKit.Color.Color.fromHexString;
	
		var color;
		if (this.options.baseColor)
			color = PlotKit.Base.palette(hexColor(this.options.baseColor));
		else {
			var colors = this.options.colorRamp.colors;
			if (groupVar.length > colors.length) {
				for (var i=0; i<this.ogColors.length; i++) {
					colors.push(this.ogColors[i]);
				}
			}
			color = this.options.colorRamp.convertToHex();
		}
	
		var shouldFill = true;
		if (this.options.type == PChartOptions.LINE)
			shouldFill = false;
	
		var paddingLeft = 70;
		if (this.options.type == PChartOptions.PIE)
			paddingLeft = 0;
		
		this.renderOptions = {
		   "colorScheme": color,
		   "padding": {left: paddingLeft, right: -1, top: 10, bottom: 30},
		   "shouldFill": shouldFill,
		   "backgroundColor": hexColor(this.options.backgroundColor),
		   "displayValue": this.options.displayValue
		};
	
		var charttype = "bar";
		if (this.options.type == PChartOptions.LINE)
			charttype = "line";
		else if (this.options.type == PChartOptions.PIE)
			charttype = "pie";
	
		var layout = new PlotKit.Layout(charttype, this.layoutOptions);
	
		for (var i=0; i<data.length; i++)
			layout.addDataset(i, data[i]);
	
		layout.evaluate();
	
		var plotter;
		
		var plotter = new PlotKit.SweetSVGRenderer(this.canvas, layout, this.renderOptions);
		plotter.render();
	}
	
	
	
	
	/*
	PlotKit SVG
	===========
	SVG Renderer for PlotKit
	
	Copyright
	---------
	Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
	For use under the BSD license. <http://www.liquidx.net/plotkit>
	*/
	
	//-------------------------------------------------------------------------
	//NOTES: - If you use XHTML1.1 strict, then you must include each MochiKit
	//      file individuall.
	//    - For IE support, you must include the AdobeSVG object hack.
	//      See tests/svg.html for details.
	//-------------------------------------------------------------------------
	//-------------------------------------------------------------------------
	//Check required components
	//-------------------------------------------------------------------------
	
	try {    
	if (typeof(PlotKit.Layout) == 'undefined')
	{
	    throw "";    
	}
	} 
	catch (e) {    
	throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Layout"
	}
	
	
	//---------------------------------------------------------------------------
	//SVG Renderer
	//---------------------------------------------------------------------------
	
	PlotKit.SVGRenderer = function(element, layout, options) {
	if (arguments.length > 0) 
	    this.__init__(element, layout, options);
	};
	
	PlotKit.SVGRenderer.NAME = "PlotKit.SVGRenderer";
	PlotKit.SVGRenderer.VERSION = PlotKit.VERSION;
	
	PlotKit.SVGRenderer.__repr__ = function() {
	return "[" + this.NAME + " " + this.VERSION + "]";
	};
	
	PlotKit.SVGRenderer.toString = function() {
	return this.__repr__();
	}
	
	PlotKit.SVGRenderer.SVGNS = 'http://www.w3.org/2000/svg';
	
	PlotKit.SVGRenderer.prototype.__init__ = function(element, layout, options) {
	var isNil = MochiKit.Base.isUndefinedOrNull;
	
	// default options
	this.options = {
	    "drawBackground": true,
	    "backgroundColor": Color.whiteColor(),
	    "padding": {left: 30, right: 30, top: 5, bottom: 10},
	    "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),
	    "strokeColor": Color.whiteColor(),
	    "strokeColorTransform": "asStrokeColor",
	    "strokeWidth": 0.5,
	    "shouldFill": true,
	    "shouldStroke": true,
	    "drawXAxis": true,
	    "drawYAxis": true,
	    "axisLineColor": Color.blackColor(),
	    "axisLineWidth": 0.5,
	    "axisTickSize": 3,
	    "axisLabelColor": Color.blackColor(),
	    "axisLabelFont": "Arial",
	    "axisLabelFontSize": 9,
	    "axisLabelWidth": 50,
	    "axisLabelUseDiv": true,
	    "pieRadius": 0.4,
	    "enableEvents": true
	};
	
	MochiKit.Base.update(this.options, options ? options : {});
	this.layout = layout;
	this.element = MochiKit.DOM.getElement(element);
	this.container = this.element.parentNode;
	this.height = parseInt(this.element.getAttribute("height"));
	this.width = parseInt(this.element.getAttribute("width"));
	this.document = document;
	this.root = this.element;
	
	// Adobe SVG Support:
	// - if an exception is thrown, then no Adobe SVG Plugin support.
	try {
	    this.document = this.element.getSVGDocument();
	    this.root = isNil(this.document.documentElement) ? this.element : this.document.documentElement;
	}
	catch (e) {
	}
	
	this.element.style.zIndex = 1;
	
	if (isNil(this.element))
	    throw "SVGRenderer() - passed SVG object is not found";
	
	if (isNil(this.container) || this.container.nodeName.toLowerCase() != "div")
	    throw "SVGRenderer() - No DIV's around the SVG.";
	
	// internal state
	this.xlabels = new Array();
	this.ylabels = new Array();
	
	// initialise some meta structures in SVG
	this.defs = this.createSVGElement("defs");
	
	this.area = {
	    x: this.options.padding.left,
	    y: this.options.padding.top,
	    w: this.width - this.options.padding.left - this.options.padding.right,
	    h: this.height - this.options.padding.top - this.options.padding.bottom
	};
	
	MochiKit.DOM.updateNodeAttributes(this.container, 
	{"style":{ "position": "relative", "width": this.width + "px"}});
	
	
	};
	
	
	PlotKit.SVGRenderer.prototype.render = function() {
	if (this.options.drawBackground)
	    this._renderBackground();
	
	if (this.layout.style == "bar") {
	    this._renderBarChart();
	    this._renderBarAxis();
	}
	else if (this.layout.style == "pie") {
	    this._renderPieChart();
	    this._renderPieAxis();
	}
	else if (this.layout.style == "line") {
	    this._renderLineChart();
	    this._renderLineAxis();
	}
	};
	
	PlotKit.SVGRenderer.prototype._renderBarOrLine = function(data, plotFunc, startFunc, endFunc) {
	
	var colorCount = this.options.colorScheme.length;
	var colorScheme = this.options.colorScheme;
	var setNames = MochiKit.Base.keys(this.layout.datasets);
	var setCount = setNames.length;
	
	for (var i = 0; i < setCount; i++) {
	    var setName = setNames[i];
	    var attrs = new Array();
	    var color = colorScheme[i%colorCount];
	
	    if (this.options.shouldFill)
	        attrs["fill"] = color.toRGBString();
	    else
	        attrs["fill"] = "none";
	
	    if (this.options.shouldStroke && 
	        (this.options.strokeColor || this.options.strokeColorTransform)) {
	        if (this.options.strokeColor)
	            attrs["stroke"] = this.options.strokeColor.toRGBString();
	        else if (this.options.strokeColorTransform)
	            attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString();
	        attrs["strokeWidth"] = this.options.strokeWidth;
	    }
	
	    if (startFunc)
	        startFunc(attrs);
	
	    var forEachFunc = function(obj) {
	        if (obj.name == setName)
	            plotFunc(attrs, obj);
	    };                
	
	    MochiKit.Iter.forEach(data, bind(forEachFunc, this));
	    if (endFunc)
	        endFunc(attrs);
	}
	};
	
	PlotKit.SVGRenderer.prototype._renderBarChart = function() {
	var bind = MochiKit.Base.bind;
	
	var drawRect = function(attrs, bar) {
	    var x = this.area.w * bar.x + this.area.x;
	    var y = this.area.h * bar.y + this.area.y;
	    var w = this.area.w * bar.w;
	    var h = this.area.h * bar.h;
	    this._drawRect(x, y, w, h, attrs);
	};
	this._renderBarOrLine(this.layout.bars, bind(drawRect, this));
	};
	
	PlotKit.SVGRenderer.prototype._renderLineChart = function() {
	var bind = MochiKit.Base.bind;
	
	var addPoint = function(attrs, point) {
	    this._tempPointsBuffer += (this.area.w * point.x + this.area.x) + "," +
	                             (this.area.h * point.y + this.area.y) + " ";
	};
	
	var startLine = function(attrs) {
	    this._tempPointsBuffer = "";
	    this._tempPointsBuffer += (this.area.x) + "," + (this.area.y+this.area.h) + " ";
	};
	
	var endLine = function(attrs) {
	    this._tempPointsBuffer += (this.area.w + this.area.x) + ","  +(this.area.h + this.area.y);
	    attrs["points"] = this._tempPointsBuffer;
	    var elem = this.createSVGElement("polygon", attrs);
	    this.root.appendChild(elem);
	};
	
	this._renderBarOrLine(this.layout.points, 
	                      bind(addPoint, this), 
	                      bind(startLine, this), 
	                      bind(endLine, this));
	};
	
	
	PlotKit.SVGRenderer.prototype._renderPieChart = function() {
	var colorCount = this.options.colorScheme.length;
	var slices = this.layout.slices;
	
	var centerx = this.area.x + this.area.w * 0.5;
	var centery = this.area.y + this.area.h * 0.5;
	var radius = Math.min(this.area.w * this.options.pieRadius, 
	                      this.area.h * this.options.pieRadius);
	
	// NOTE NOTE!! Canvas Tag draws the circle clockwise from the y = 0, x = 1
	// so we have to subtract 90 degrees to make it start at y = 1, x = 0
	
	// workaround if we only have 1 slice of 100%
	if (slices.length == 1 && (Math.abs(slices[0].startAngle) - Math.abs(slices[0].endAngle) < 0.1)) {
	    var attrs = {"cx": centerx , "cy": centery , "r": radius };
	    var color = this.options.colorScheme[0];
	    if (this.options.shouldFill)
	        attrs["fill"] = color.toRGBString();
	    else
	        attrs["fill"] = "none";
	
	    if (this.options.shouldStroke && 
	        (this.options.strokeColor || this.options.strokeColorTransform)) {
	        if (this.options.strokeColor)
	            attrs["stroke"] = this.options.strokeColor.toRGBString();
	        else if (this.options.strokeColorTransform)
	            attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString();
	        attrs["style"] = "stroke-width: " + this.options.strokeWidth;
	    }
	
	    this.root.appendChild(this.createSVGElement("circle", attrs));
	    return;
	}
	
	for (var i = 0; i < slices.length; i++) {
	    var attrs = new Array();
	    var color = this.options.colorScheme[i%colorCount];
	    if (this.options.shouldFill)
	        attrs["fill"] = color.toRGBString();
	    else
	        attrs["fill"] = "none";
	
	    if (this.options.shouldStroke &&
	        (this.options.strokeColor || this.options.strokeColorTransform)) {
	        if (this.options.strokeColor)
	            attrs["stroke"] = this.options.strokeColor.toRGBString();
	        else if (this.options.strokeColorTransform)
	            attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString();
	        attrs["style"] = "stroke-width:" + this.options.strokeWidth;
	    }
	
	    var largearc = 0;
	    if (Math.abs(slices[i].endAngle - slices[i].startAngle) > Math.PI)
	        largearc = 1;
	    var x1 = Math.cos(slices[i].startAngle - Math.PI/2) * radius;
	    var y1 = Math.sin(slices[i].startAngle - Math.PI/2) * radius;
	    var x2 = Math.cos(slices[i].endAngle - Math.PI/2) * radius;
	    var y2 = Math.sin(slices[i].endAngle - Math.PI/2) * radius;
	    var rx = x2 - x1;
	    var ry = y2 - y1;
	
	    var pathString = "M" + centerx + "," + centery + " ";       
	    pathString += "l" + x1 + "," + y1 + " ";
	    pathString += "a" + radius + "," + radius + " 0 " + largearc + ",1 " + rx + "," + ry + " z";
	
	    attrs["d"] = pathString;
	
	    var elem = this.createSVGElement("path", attrs);
	    this.root.appendChild(elem);
	}
	};
	
	PlotKit.SVGRenderer.prototype._renderBarAxis = function() {
	this._renderAxis();
	}
	
	PlotKit.SVGRenderer.prototype._renderLineAxis = function() {
	this._renderAxis();
	};
	
	
	PlotKit.SVGRenderer.prototype._renderAxis = function() {
	
	if (!this.options.drawXAxis && !this.options.drawYAxis)
	    return;
	
	var labelStyle = {"style":
	     {"position": "absolute",
	      "textAlign": "center",
	      "fontSize": this.options.axisLabelFontSize + "px",
	      "zIndex": 10,
	      "color": this.options.axisLabelColor.toRGBString(),
	      "width": this.options.axisLabelWidth + "px",
	      "overflow": "hidden"
	     }
	};
	
	// axis lines
	var lineAttrs = {
	    "stroke": this.options.axisLineColor.toRGBString(),
	    "strokeWidth": this.options.axisLineWidth
	};
	
	
	if (this.options.drawYAxis) {
	    if (this.layout.yticks) {
	        var drawTick = function(tick) {
	            var x = this.area.x;
	            var y = this.area.y + tick[0] * this.area.h;
	            this._drawLine(x, y, x - 3, y, lineAttrs);
	            
	            if (this.options.axisLabelUseDiv) {
	                var label = DIV(labelStyle, tick[1]);
	                label.style.top = (y - this.options.axisLabelFontSize) + "px";
	                label.style.left = (x - this.options.padding.left + this.options.axisTickSize) + "px";
	                label.style.textAlign = "left";
	                label.style.width = (this.options.padding.left - 3) + "px";
	                MochiKit.DOM.appendChildNodes(this.container, label);
	                this.ylabels.push(label);
	            }
	            else {
	                var attrs = {
	                    y: y + 3,
	                    x: (x - this.options.padding.left + 3),
	                    width: (this.options.padding.left - this.options.axisTickSize) + "px",
	                    height: (this.options.axisLabelFontSize + 3) + "px",
	                    fontFamily: "Arial",
	                    fontSize: this.options.axisLabelFontSize + "px",
	                    fill: this.options.axisLabelColor.toRGBString()
	                };
	                
	                /* we can do clipping just like DIVs
	                http://www.xml.com/pub/a/2004/06/02/svgtype.html */
	                /*
	                var mask = this.createSVGElement("mask", {id: "mask" + tick[0]});
	                var maskShape = this.createSVGElement("rect",
	                    {y: y + 3,
	                     x: (x - this.options.padding.left + 3),
	                     width: (this.options.padding.left - this.options.axisTickSize) + "px",
	                     height: (this.options.axisLabelFontSize + 3) + "px",
	                     style: {"fill": "#ffffff", "stroke": "#000000"}});
	                mask.appendChild(maskShape);
	                this.defs.appendChild(mask);
	                
	                attrs["filter"] = "url(#mask" + tick[0] + ")";
	                */
	                
	                var label = this.createSVGElement("text", attrs);
	                label.appendChild(this.document.createTextNode(tick[1]));
	                this.root.appendChild(label);
	            }
	        };
	        
	        MochiKit.Iter.forEach(this.layout.yticks, bind(drawTick, this));
	    }
	
	    this._drawLine(this.area.x, this.area.y, this.area.x, this.area.y + this.area.h, lineAttrs);
	}
	
	if (this.options.drawXAxis) {
	    if (this.layout.xticks) {
	        var drawTick = function(tick) {
	            var x = this.area.x + tick[0] * this.area.w;
	            var y = this.area.y + this.area.h;
	            this._drawLine(x, y, x, y + this.options.axisTickSize, lineAttrs);
	
	            if (this.options.axisLabelUseDiv) {
	                var label = DIV(labelStyle, tick[1]);
	                label.style.top = (y + this.options.axisTickSize) + "px";
	                label.style.left = (x - this.options.axisLabelWidth/2) + "px";
	                label.style.textAlign = "center";
	                label.style.width = this.options.axisLabelWidth + "px";
	                MochiKit.DOM.appendChildNodes(this.container, label);
	                this.xlabels.push(label);
	            }
	            else {
	                var attrs = {
	                    y: (y + this.options.axisTickSize + this.options.axisLabelFontSize),
	                    x: x - 3,
	                    width: this.options.axisLabelWidth + "px",
	                    height: (this.options.axisLabelFontSize + 3) + "px",
	                    fontFamily: "Arial",
	                    fontSize: this.options.axisLabelFontSize + "px",
	                    fill: this.options.axisLabelColor.toRGBString(),
	                    textAnchor: "middle"
	                };
	                var label = this.createSVGElement("text", attrs);
	                label.appendChild(this.document.createTextNode(tick[1]));
	                this.root.appendChild(label);
	            }
	        };
	        
	        MochiKit.Iter.forEach(this.layout.xticks, bind(drawTick, this));
	    }
	
	    this._drawLine(this.area.x, this.area.y + this.area.h, this.area.x + this.area.w, this.area.y + this.area.h, lineAttrs)
	}
	};
	
	PlotKit.SVGRenderer.prototype._renderPieAxis = function() {
	
	if (this.layout.xticks) {
	    // make a lookup dict for x->slice values
	    var lookup = new Array();
	    for (var i = 0; i < this.layout.slices.length; i++) {
	        lookup[this.layout.slices[i].xval] = this.layout.slices[i];
	    }
	    
	    var centerx = this.area.x + this.area.w * 0.5;
	    var centery = this.area.y + this.area.h * 0.5;
	    var radius = Math.min(this.area.w * this.options.pieRadius + 10, 
	                          this.area.h * this.options.pieRadius + 10);
	    var labelWidth = this.options.axisLabelWidth;
	    
	    for (var i = 0; i < this.layout.xticks.length; i++) {
	        var slice = lookup[this.layout.xticks[i][0]];
	        if (MochiKit.Base.isUndefinedOrNull(slice))
	            continue;
	            
	            
	        var angle = (slice.startAngle + slice.endAngle)/2;
	        // normalize the angle
	        var normalisedAngle = angle;
	        if (normalisedAngle > Math.PI * 2)
	            normalisedAngle = normalisedAngle - Math.PI * 2;
	        else if (normalisedAngle < 0)
	            normalisedAngle = normalisedAngle + Math.PI * 2;
	            
	        var labelx = centerx + Math.sin(normalisedAngle) * (radius + 10);
	        var labely = centery - Math.cos(normalisedAngle) * (radius + 10);
	
	        var attrib = {
	            "position": "absolute",
	             "zIndex": 11,
	            "width": labelWidth + "px",
	            "fontSize": this.options.axisLabelFontSize + "px",
	            "overflow": "hidden",
	            "color": this.options.axisLabelColor.toHexString()
	        };
	
	        var svgattrib = {
	            "width": labelWidth + "px",
	            "fontSize": this.options.axisLabelFontSize + "px",
	            "height": (this.options.axisLabelFontSize + 3) + "px",
	            "fill": this.options.axisLabelColor.toRGBString()
	        };
	
	        if (normalisedAngle <= Math.PI * 0.5) {
	            // text on top and align left
	            MochiKit.Base.update(attrib, {
	                'textAlign': 'left', 'verticalAlign': 'top',
	                'left': labelx + 'px',
	                'top':  (labely - this.options.axisLabelFontSize) + "px"
	            });
	            MochiKit.Base.update(svgattrib, {
	                "x": labelx,
	                "y" :(labely - this.options.axisLabelFontSize),
	                "textAnchor": "left"
	                    });
	        }
	        else if ((normalisedAngle > Math.PI * 0.5) && (normalisedAngle <= Math.PI)) {
	            // text on bottom and align left
	            MochiKit.Base.update(attrib, {
	                'textAlign': 'left', 'verticalAlign': 'bottom',
	                'left': labelx + 'px',
	                'top':  labely + "px"
	            });
	            MochiKit.Base.update(svgattrib, {
	                'textAnchor': 'left',
	                'x': labelx,
	                'y':  labely
	            });
	        }
	        else if ((normalisedAngle > Math.PI) && (normalisedAngle <= Math.PI*1.5)) {
	            // text on bottom and align right
	            MochiKit.Base.update(attrib, {
	                'textAlign': 'right', 'verticalAlign': 'bottom',
	                'left': labelx + 'px',
	                'top':  labely + "px"
	            });
	            MochiKit.Base.update(svgattrib, {
	                'textAnchor': 'right',
	                'x': labelx - labelWidth,
	                'y':  labely
	            });
	        }
	        else {
	            // text on top and align right
	            MochiKit.Base.update(attrib, {
	                'textAlign': 'left', 'verticalAlign': 'bottom',
	                'left': labelx + 'px',
	                'top':  labely + "px"
	            });
	            MochiKit.Base.update(svgattrib, {
	                'textAnchor': 'left',
	                'x': labelx - labelWidth,
	                'y':  labely - this.options.axisLabelFontSize
	            });
	        }
	
	        if (this.options.axisLabelUseDiv) {
	            var label = DIV({'style': attrib}, this.layout.xticks[i][1]);
	            this.xlabels.push(label);
	            MochiKit.DOM.appendChildNodes(this.container, label);
	        }
	        else {
	            var label = this.createSVGElement("text", svgattrib);
	            label.appendChild(this.document.createTextNode(this.layout.xticks[i][1]))
	            this.root.appendChild(label);
	        }
	  }
	    
	}
	};
	
	PlotKit.SVGRenderer.prototype._renderBackground = function() {
	var opts = {"stroke": "none",
	              "fill": this.options.backgroundColor.toRGBString()
	};
	this._drawRect(0, 0, this.width, this.height, opts);
	};
	
	PlotKit.SVGRenderer.prototype._drawRect = function(x, y, w, h, moreattrs) {
	var attrs = {x: x + "px", y: y + "px", width: w + "px", height: h + "px"};
	if (moreattrs)
	    MochiKit.Base.update(attrs, moreattrs);
	
	var elem = this.createSVGElement("rect", attrs);
	this.root.appendChild(elem);
	};
	
	PlotKit.SVGRenderer.prototype._drawLine = function(x1, y1, x2, y2, moreattrs) {
	var attrs = {x1: x1 + "px", y1: y1 + "px", x2: x2 + "px", y2: y2 + "px"};
	if (moreattrs)
	    MochiKit.Base.update(attrs, moreattrs);
	
	var elem = this.createSVGElement("line", attrs);
	this.root.appendChild(elem);
	}
	
	PlotKit.SVGRenderer.prototype.clear = function() {
	while(this.element.firstChild) {
	    this.element.removeChild(this.element.firstChild);
	}
	
	if (this.options.axisLabelUseDiv) {
	    for (var i = 0; i < this.xlabels.length; i++) {
	        MochiKit.DOM.removeElement(this.xlabels[i]);
	    }        
	    for (var i = 0; i < this.ylabels.length; i++) {
	        MochiKit.DOM.removeElement(this.ylabels[i]);
	    }            
	}
	this.xlabels = new Array();
	this.ylabels = new Array();
	};
	
	
	PlotKit.SVGRenderer.prototype.createSVGElement = function(name, attrs) {
	var isNil = MochiKit.Base.isUndefinedOrNull;
	var elem;
	var doc = isNil(this.document) ? document : this.document;
	
	try {
	    elem = doc.createElementNS(PlotKit.SVGRenderer.SVGNS, name);
	}
	catch (e) {
	    elem = doc.createElement(name);
	    elem.setAttribute("xmlns", PlotKit.SVGRenderer.SVGNS);
	}
	
	if (attrs)
	    MochiKit.DOM.updateNodeAttributes(elem, attrs);
	
	// TODO: we don't completely emulate the MochiKit.DOM.createElement
	//       as we don't care about nodes contained. We really should though.
	
	return elem;
	
	};
	
	
	PlotKit.SVGRenderer.SVG = function(attrs) {
	// we have to do things differently for IE+AdobeSVG.
	// My guess this works (via trial and error) is that we need to
	// have an SVG object in order to use SVGDocument.createElementNS
	// but IE doesn't allow us to that.
	
	var ie = navigator.appVersion.match(/MSIE (\d\.\d)/);
	var opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
	if (ie && (ie[1] >= 6) && (!opera)) {
	    var width = attrs["width"] ? attrs["width"] : "100";
	    var height = attrs["height"] ? attrs["height"] : "100";
	    var eid = attrs["id"] ? attrs["id"] : "notunique";
	    
	    var html = '<svg:svg width="' + width + '" height="' + height + '" ';
	    html += 'id="' + eid + '" version="1.1" baseProfile="full" />';
	
	    var canvas = document.createElement(html);
	
	    // create embedded SVG inside SVG.
	    var group = canvas.getSVGDocument().createElementNS(PlotKit.SVGRenderer.SVGNS, "svg");
	    group.setAttribute("width", width);
	    group.setAttribute("height", height);
	    canvas.getSVGDocument().appendChild(group);
	
	    return canvas;
	}
	else {
	    return PlotKit.SVGRenderer.prototype.createSVGElement("svg", attrs);
	}
	};
	
	PlotKit.SVGRenderer.isSupported = function() {
	var isOpera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
	var ieVersion = navigator.appVersion.match(/MSIE (\d\.\d)/);
	var safariVersion = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
	var operaVersion = navigator.userAgent.match(/Opera\/(\d*\.\d*)/);
	var mozillaVersion = navigator.userAgent.match(/rv:(\d*\.\d*).*Gecko/);
	var svgFeature = "http://www.w3.org/TR/SVG11/feature#SVG";
	
	if (ieVersion && (ieVersion[1] >= 6) && !isOpera) {
	    return document.implementation.hasFeature(svgFeature,"1.1");
	    /*
	    var dummysvg = document.createElement('<svg:svg width="1" height="1" baseProfile="full" version="1.1" id="dummy">');
	    try {
	        dummysvg.getSVGDocument();
	        dummysvg = null;
	        return true;
	    }
	    catch (e) {
	        return false;
	    }
	    */
	    
	}
	
	/* support not really there yet. no text and paths are buggy
	if (safariVersion && (safariVersion[1] > 419))
	    return true;
	*/
	
	if (operaVersion && (operaVersion[1] > 8.9))
	    return true
	
	if (mozillaVersion && (mozillaVersion > 1.7))
	    return true;
	
	return false;
	};
	
	//Namespace Iniitialisation
	
	PlotKit.SVG = {}
	PlotKit.SVG.SVGRenderer = PlotKit.SVGRenderer;
	
	PlotKit.SVG.EXPORT = [
	"SVGRenderer"
	];
	
	PlotKit.SVG.EXPORT_OK = [
	"SVGRenderer"
	];
	
	PlotKit.SVG.__new__ = function() {
	var m = MochiKit.Base;
	
	m.nameFunctions(this);
	
	this.EXPORT_TAGS = {
	    ":common": this.EXPORT,
	    ":all": m.concat(this.EXPORT, this.EXPORT_OK)
	};
	};
	
	PlotKit.SVG.__new__();
	MochiKit.Base._exportSymbols(this, PlotKit.SVG);
	
	/*
	PlotKit Sweet SVG Renderer
	==========================
	SVG Renderer for PlotKit which looks pretty!
	
	Copyright
	---------
	Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
	For use under the BSD license. <http://www.liquidx.net/plotkit>
	*/
	
	
	//-------------------------------------------------------------------------
	//Check required components
	//-------------------------------------------------------------------------
	
	try {    
	if (typeof(PlotKit.SVGRenderer) == 'undefined')
	{
	    throw "";    
	}
	} 
	catch (e) {    
	throw "SweetSVG depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, SVG}"
	}
	
	
	if (typeof(PlotKit.SweetSVGRenderer) == 'undefined') {
	PlotKit.SweetSVGRenderer = {};
	}
	
	PlotKit.SweetSVGRenderer = function(element, layout, options) {
	if (arguments.length > 0) {
	    this.__init__(element, layout, options);
	}
	};
	
	PlotKit.SweetSVGRenderer.NAME = "PlotKit.SweetSVGRenderer";
	PlotKit.SweetSVGRenderer.VERSION = PlotKit.VERSION;
	
	PlotKit.SweetSVGRenderer.__repr__ = function() {
	return "[" + this.NAME + " " + this.VERSION + "]";
	};
	
	PlotKit.SweetSVGRenderer.toString = function() {
	return this.__repr__();
	};
	
	//---------------------------------------------------------------------
	//Subclassing Magic
	//---------------------------------------------------------------------
	
	PlotKit.SweetSVGRenderer.prototype = new PlotKit.SVGRenderer();
	PlotKit.SweetSVGRenderer.prototype.constructor = PlotKit.SweetSVGRenderer;
	PlotKit.SweetSVGRenderer.__super__ = PlotKit.SVGRenderer.prototype;
	
	//---------------------------------------------------------------------
	//Constructor
	//---------------------------------------------------------------------
	
	PlotKit.SweetSVGRenderer.prototype.__init__ = function(element, layout, options) { 
	var moreOpts = PlotKit.Base.officeBlue();
	MochiKit.Base.update(moreOpts, options);
	PlotKit.SweetSVGRenderer.__super__.__init__.call(this, element, layout, moreOpts);
	//this._addDropShadowFilter();
	};
	
	PlotKit.SweetSVGRenderer.prototype._addDropShadowFilter = function() {
	var filter = this.createSVGElement("filter", {x: 0, y: 0, "id":"dropShadow"});
	var goffset = this.createSVGElement("feOffset",
	    {"in": "SourceGraphic", "dx": 0, "dy": 0, "result": "topCopy"});
	var blur = this.createSVGElement("feGaussianBlur",
	    {"in": "SourceAlpha", "StdDeviation": 2, "result": "shadow"});
	var soffset = this.createSVGElement("feOffset",
	    {"in": "shadow", "dx": -1, "dy": -2, "result":"movedShadow"});
	var merge = this.createSVGElement("feMerge");
	var gmerge = this.createSVGElement("feMergeNode", {"in":"topCopy"});
	var smerge = this.createSVGElement("feMergeNode", {"in":"movedShadow"});
	
	merge.appendChild(gmerge);
	merge.appendChild(smerge);
	filter.appendChild(goffset);
	filter.appendChild(blur);
	filter.appendChild(soffset);
	filter.appendChild(merge);
	this.defs.appendChild(filter);
	};
	
	//---------------------------------------------------------------------
	//Extended Plotting Functions
	//---------------------------------------------------------------------
	
	PlotKit.SweetSVGRenderer.prototype._renderBarChart = function() {
	var bind = MochiKit.Base.bind;
	var shadowColor = Color.blackColor().toRGBString();
	var shadowStyle = "fill:" + shadowColor + ";fill-opacity:0.15";
	var strokeStyle = "stroke-width: 2.0; stroke:" + Color.whiteColor().toRGBString();
	
	var drawRect = function(attrs, bar) {
	    var x = this.area.w * bar.x + this.area.x;
	    var y = this.area.h * bar.y + this.area.y;
	    var w = this.area.w * bar.w;
	    var h = this.area.h * bar.h;
	
	    if ((w < 1) || (h < 1))
	        return;        
	
	    //attrs["filter"] = "url(#dropShadow)";
	    attrs["style"] = strokeStyle;
	    this._drawRect(x - 2, y - 1, w+4, h+2, {"style":shadowStyle});
	    this._drawRect(x, y, w, h, attrs);
	};
	this._renderBarOrLine(this.layout.bars, bind(drawRect, this));
	
	};
	
	PlotKit.SweetSVGRenderer.prototype._renderLineChart = function() {
	var bind = MochiKit.Base.bind;
	var shadowColor = Color.blackColor().toRGBString();
	var shadowStyle = "fill:" + shadowColor + ";fill-opacity:0.15";
	var strokeStyle = "stroke-width: 2.0; stroke:" + Color.whiteColor().toRGBString();
	
	var addPoint = function(attrs, point) {
	    this._tempPointsBuffer += (this.area.w * point.x + this.area.x) + "," +
	                             (this.area.h * point.y + this.area.y) + " ";
	};
	
	var startLine = function(attrs) {
	    this._tempPointsBuffer = "";
	    this._tempPointsBuffer += (this.area.x) + "," + (this.area.y+this.area.h) + " ";
	};
	
	var endLine = function(attrs) {
	    this._tempPointsBuffer += (this.area.w + this.area.x) + ","  +(this.area.h + this.area.y);
	    attrs["points"] = this._tempPointsBuffer;    
	        
	    attrs["stroke"] = "none";
	    attrs["transform"] = "translate(-2, -1)";
	    attrs["style"] = shadowStyle;
	    var shadow = this.createSVGElement("polygon", attrs);
	    this.root.appendChild(shadow);
	    
	    attrs["transform"] = "";
	    attrs["style"] = strokeStyle;
	    var elem = this.createSVGElement("polygon", attrs);
	    this.root.appendChild(elem);
	    
	   
	};
	
	this._renderBarOrLine(this.layout.points, 
	                         bind(addPoint, this), 
	                         bind(startLine, this), 
	                         bind(endLine, this));
	};
	
	PlotKit.SweetSVGRenderer.prototype._renderPieChart = function() {
	var centerx = this.area.x + this.area.w * 0.5;
	var centery = this.area.y + this.area.h * 0.5;
	var shadowColor = Color.blackColor().toRGBString();
	var radius = Math.min(this.area.w * this.options.pieRadius, 
	                      this.area.h * this.options.pieRadius);
	var shadowStyle = "fill:" + shadowColor + ";fill-opacity:0.15";
	
	var shadow = this.createSVGElement("circle", 
	    {"style": shadowStyle, "cx": centerx + 1, "cy": centery + 1, "r": radius + 1});
	this.root.appendChild(shadow);
	                         
	PlotKit.SweetSVGRenderer.__super__._renderPieChart.call(this);
	};
	
	
	PlotKit.SweetSVGRenderer.prototype._renderBackground = function() {
	var attrs = {
	    "fill": this.options.backgroundColor.toRGBString(),
	    "stroke": "none"
	};
	
	
	if (this.layout.style == "bar" || this.layout.style == "line") {
	    this._drawRect(this.area.x, this.area.y, 
	                   this.area.w, this.area.h, attrs);
	                   
	    var ticks = this.layout.yticks;
	    var horiz = false;
	    if (this.layout.style == "bar" && 
	        this.layout.options.barOrientation == "horizontal") {
	            ticks = this.layout.xticks;
	            horiz = true;
	    }
	    
	    for (var i = 0; i < ticks.length; i++) {
	        var x = 0;
	        var y = 0;
	        var w = 0;
	        var h = 0;
	        
	        if (horiz) {
	            x = ticks[i][0] * this.area.w + this.area.x;
	            y = this.area.y;
	            w = 1;
	            h = this.area.w;
	        }
	        else {
	            x = this.area.x;
	            y = ticks[i][0] * this.area.h + this.area.y;
	            w = this.area.w;
	            h = 1;
	        }
	        
	        this._drawRect(x, y, w, h,
	                       {"fill": this.options.axisLineColor.toRGBString()});
	    }
	}
	else {
	    PlotKit.SweetSVGRenderer.__super__._renderBackground.call(this);
	    
	}
	
	};
	
	//Namespace Iniitialisation
	
	PlotKit.SweetSVG = {}
	PlotKit.SweetSVG.SweetSVGRenderer = PlotKit.SweetSVGRenderer;
	
	PlotKit.SweetSVG.EXPORT = [
	"SweetSVGRenderer"
	];
	
	PlotKit.SweetSVG.EXPORT_OK = [
	"SweetSVGRenderer"
	];
	
	PlotKit.SweetSVG.__new__ = function() {
	var m = MochiKit.Base;
	
	m.nameFunctions(this);
	
	this.EXPORT_TAGS = {
	    ":common": this.EXPORT,
	    ":all": m.concat(this.EXPORT, this.EXPORT_OK)
	};
	};
	
	PlotKit.SweetSVG.__new__();
	MochiKit.Base._exportSymbols(this, PlotKit.SweetSVG);
	
	
	PChart.prototype.clear = function() {
		while(this.container.hasChildNodes())
			this.container.removeChild(this.container.firstChild);
	
		this.canvas = SVGRenderer.SVG({"width": parseInt(this.container.style.width), "height": parseInt(this.container.style.height), "id":"chart"});
		this.canvas.id = "chartcanvas_" + this.container.id;
		this.container.appendChild(this.canvas);
	
	}
}
