docs: function (params) {
  		_jp.jsPlumbUIComponent.apply(this, arguments);
  		AbstractOverlay.apply(this, arguments);
  
  		// hand off fired events to associated component.
  		var _f = this.fire;
  		this.fire = function () {
  			_f.apply(this, arguments);
  			if (this.component) this.component.fire.apply(this.component, arguments);
  		};
  
  		this.detached=false;
  		this.id = params.id;
  		this._jsPlumb.div = null;
  		this._jsPlumb.initialised = false;
  		this._jsPlumb.component = params.component;
  		this._jsPlumb.cachedDimensions = null;
  		this._jsPlumb.create = params.create;
  		this._jsPlumb.initiallyInvisible = params.visible === false;
  
  		this.getElement = function () {
  			if (this._jsPlumb.div == null) {
  				var div = this._jsPlumb.div = jsPlumb.getElement(this._jsPlumb.create(this._jsPlumb.component));
  				div.style.position = "absolute";
  				div.className = this._jsPlumb.instance.overlayClass + " " +
  					(this.cssClass ? this.cssClass :
  						params.cssClass ? params.cssClass : "");
  				this._jsPlumb.instance.appendElement(div);
  				this._jsPlumb.instance.getId(div);
  				this.canvas = div;
  
  				// in IE the top left corner is what it placed at the desired location.  This will not
  				// be fixed. IE8 is not going to be supported for much longer.
  				var ts = "translate(-50%, -50%)";
  				div.style.webkitTransform = ts;
  				div.style.mozTransform = ts;
  				div.style.msTransform = ts;
  				div.style.oTransform = ts;
  				div.style.transform = ts;
  
  				// write the related component into the created element
  				div._jsPlumb = this;
  
  				if (params.visible === false)
  					div.style.display = "none";
  			}
  			return this._jsPlumb.div;
  		};
  
  		this.draw = function (component, currentConnectionPaintStyle, absolutePosition) {
  			var td = _getDimensions(this);
  			if (td != null && td.length == 2) {
  				var cxy = { x: 0, y: 0 };
  
  				// absolutePosition would have been set by a call to connection.setAbsoluteOverlayPosition.
  				if (absolutePosition) {
  					cxy = { x: absolutePosition[0], y: absolutePosition[1] };
  				}
  				else if (component.pointOnPath) {
  					var loc = this.loc, absolute = false;
  					if (_ju.isString(this.loc) || this.loc < 0 || this.loc > 1) {
  						loc = parseInt(this.loc, 10);
  						absolute = true;
  					}
  					cxy = component.pointOnPath(loc, absolute);  // a connection
  				}
  				else {
  					var locToUse = this.loc.constructor == Array ? this.loc : this.endpointLoc;
  					cxy = { x: locToUse[0] * component.w,
  						y: locToUse[1] * component.h };
  				}
  
  				var minx = cxy.x - (td[0] / 2),
  					miny = cxy.y - (td[1] / 2);
  
  				return {
  					component: component,
  					d: { minx: minx, miny: miny, td: td, cxy: cxy },
  					minX: minx,
  					maxX: minx + td[0],
  					minY: miny,
  					maxY: miny + td[1]
  				};
  			}
  			else return {minX: 0, maxX: 0, minY: 0, maxY: 0};
  		};
  	}