docs: function Connector(htmlElement, canvas)
  {
  	/**
  	 * declaring html element
  	 */
  	this.htmlElement = htmlElement;
  	
  	/**
  	 * the canvas this connector is in
  	 */
  	this.canvas = canvas;
  	
  	/**
  	 * the source block
  	 */
  	this.source = null;
  	
  	/**
  	 * the destination block
  	 */
  	this.destination = null;	
  	
  	/**
  	 * preferred orientation
  	 */
  	this.preferredSourceOrientation = AUTO;
  	this.preferredDestinationOrientation = AUTO;
  	
  	/**
  	 * css class to be applied to the connector's segments
  	 */
  	this.connectorClass;
  	
  	/**
  	 * minimum length for a connector segment.
  	 */
  	this.minSegmentLength = 10;
  
  	/**
  	 * size of the connector, i.e.: thickness of the segments.
  	 */
  	this.size = 1;
  	
  	/**
  	 * connector's color
  	 */
  	this.color = 'black';
  	
  	/**
  	 * move listeners, they are notify when connector moves
  	 */
  	this.moveListeners = new Array();
  	
  	this.firstSegment;
  	
  	this.segmentsPool;
  	
  	this.segmentsNumber = 0;
  	
  	this.strategy;
  		
  	this.initConnector = function()
  	{
  		// detect the connector id
  		if(this.htmlElement.id)
  			this.id = this.htmlElement.id;
  		else
  			this.id = this.htmlElement.className;
  			
  		// split the class name to get the ids of the source and destination blocks
  		var splitted = htmlElement.className.split(' ');
  		if(splitted.length < 3)
  		{
  			alert('Unable to create connector \'' + id + '\', class is not in the correct format: connector <sourceBlockId>, <destBlockId>');
  			return;
  		}
  		
  		this.connectorClass = splitted[0] + ' ' + splitted[1] + ' ' + splitted[2];
  		
  		this.source = this.canvas.findBlock(splitted[1]);
  		if(!this.source)
  		{
  			alert('cannot find source block with id \'' + splitted[1] + '\'');
  			return;
  		}
  		
  		this.destination = this.canvas.findBlock(splitted[2]);
  		if(!this.destination)
  		{
  			// alert('cannot find destination block with id \'' + splitted[2] + '\'');
  			return;
  		}
  		
  		// check preferred orientation
  		if(hasClass(this.htmlElement, 'vertical'))
  		{
  			this.preferredSourceOrientation = VERTICAL;
  			this.preferredDestinationOrientation = VERTICAL;
  		}
  		else if(hasClass(this.htmlElement, 'horizontal'))
  		{
  			this.preferredSourceOrientation = HORIZONTAL;
  			this.preferredDestinationOrientation = HORIZONTAL;
  		}
  		else
  		{
  			// check preferred orientation on source side
  			if(hasClass(this.htmlElement, 'vertical_start'))
  				this.preferredSourceOrientation = VERTICAL;
  			else if(hasClass(this.htmlElement, 'horizontal_start'))
  				this.preferredSourceOrientation = HORIZONTAL;
  			else if(hasClass(this.htmlElement, 'left_start'))
  				this.preferredSourceOrientation = LEFT;
  			else if(hasClass(this.htmlElement, 'right_start'))
  				this.preferredSourceOrientation = RIGHT;
  			else if(hasClass(this.htmlElement, 'up_start'))
  				this.preferredSourceOrientation = UP;
  			else if(hasClass(this.htmlElement, 'down_start'))
  				this.preferredSourceOrientation = DOWN;
  			
  			// check preferred orientation on destination side
  			if(hasClass(this.htmlElement, 'vertical_end'))
  				this.preferredDestinationOrientation = VERTICAL;
  			else if(hasClass(this.htmlElement, 'horizontal_end'))
  				this.preferredDestinationOrientation = HORIZONTAL;
  			else if(hasClass(this.htmlElement, 'left_end'))
  				this.preferredDestinationOrientation = LEFT;
  			else if(hasClass(this.htmlElement, 'right_end'))
  				this.preferredDestinationOrientation = RIGHT;
  			else if(hasClass(this.htmlElement, 'up_end'))
  				this.preferredDestinationOrientation = UP;
  			else if(hasClass(this.htmlElement, 'down_end'))
  				this.preferredDestinationOrientation = DOWN;
  		}
  		
  		// get the first strategy as default
  		this.strategy = strategies[0](this);
  		this.repaint();
  		
  		this.source.moveListeners.push(this);
  		this.destination.moveListeners.push(this);
  		
  		// call inspectors for this connector
  		var i;
  		for(i = 0; i < inspectors.length; i++)
  		{
  			inspectors[i].inspect(this);
  		}
  		
  		// remove old html element
  		this.htmlElement.parentNode.removeChild(this.htmlElement);
  	}
  	
  	this.getStartSegment = function() {
  		return this.firstSegment;
  	}
  	
  	this.getEndSegment = function() {
  		var s = this.firstSegment;
  		while (s.nextSegment)
  			s = s.nextSegment;
  		return s;
  	}
  	
  	this.getMiddleSegment = function() {
  		return this.strategy?  this.strategy.getMiddleSegment(): null;
  	}
  	
  	this.createSegment = function() {
  		var segment;
  		
  		// if the pool contains more objects, borrow the segment, create it otherwise
  		if(this.segmentsPool) {
  			segment = this.segmentsPool;
  			this.segmentsPool = this.segmentsPool.detach();
  		} else {		
  			segment = new Segment(this.id + "_" + (this.segmentsNumber + 1), this.canvas.htmlElement);
  			segment.htmlElement.className = this.connectorClass;
  			if(!getStyle(segment.htmlElement, 'background-color'))
  				segment.htmlElement.style.backgroundColor = this.color;
  			segment.thickness = this.size;
  		}
  		this.segmentsNumber++;
  		
  		if(this.firstSegment)
  			this.firstSegment.append(segment);
  		else
  			this.firstSegment = segment;
  		segment.visible = true;
  		return segment;
  	}
  	
  	/**
  	 * Repaints the connector
  	 */
  	this.repaint = function() {
  		// check strategies fitness and choose the best fitting one
  		var maxFitness = 0;
  		var fitness;
  		var s;
  		
  		// check if any strategy is possible with preferredOrientation
  		for(var i = 0; i < strategies.length; i++) {
  			this.clearSegments();
  			
  			fitness = 0;
  			s = strategies[i](this);
  			if(s.isApplicable()) {
  				fitness++;
  				s.paint();
  				// check resulting orientation against the preferred orientations
  				if((this.firstSegment.orientation & this.preferredSourceOrientation) != 0)
  					fitness++;
  				if((this.getEndSegment().orientation & this.preferredDestinationOrientation) != 0)
  					fitness++;
  			}
  			
  			if(fitness > maxFitness) {
  				this.strategy = s;
  				maxFitness = fitness;
  			}
  		}			
  		
  		this.clearSegments();
  
  		this.strategy.paint();
  		this.firstSegment.draw();
  
  		// this is needed to actually hide unused html elements	
  		if(this.segmentsPool)
  			this.segmentsPool.draw();
  	}
  	
  	/**
  	 * Hide all the segments and return them to pool
  	 */
  	this.clearSegments = function() {
  		if (this.firstSegment) {
  			this.firstSegment.cascadeHide();
  			this.firstSegment.append(this.segmentsPool);
  			this.segmentsPool = this.firstSegment;
  			this.firstSegment = null;
  		}	
  	}
  		
  	this.onMove = function() {
  		this.repaint();
  		// notify listeners
  		for (var i = 0; i < this.moveListeners.length; i++)
  			this.moveListeners[i].onMove();
  	}
  }