text: function JsonProperty(object){
  	this.object = object || {};
  }
  JsonProperty.prototype.reset = function(object){
  	return this.object = object;
  }
  JsonProperty.prototype.set = function(key,value){
  	return this.object[key] = value;
  }
  JsonProperty.prototype.get = function(key){
  	return this.object[key]
  }
  function SpiderEditor(options){
  	options = options || {};
  	var emptyFunction = function(){}
  	this.selectedCellListener = options.selectedCellListener || emptyFunction;
  	if(mxClient.isBrowserSupported()){
  		this.editor = new mxEditor();
  		this.editor.setGraphContainer(options.element);
  		this.graph = this.editor.graph;
  		this.graph.setConnectable(true);
  		this.graph.setMultigraph(false);	//禁止重复连接
  		this.graph.setAllowLoops(true);		//允许自己连自己
  		this.graph.isHtmlLabel = function(cell){
  			return !this.isSwimlane(cell);
  		}
  		mxConstants.MIN_HOTSPOT_SIZE = 16;
  		mxGraphHandler.prototype.guidesEnabled = true
  		//注册json编码器
  		this.registerJsonCodec();
  		//配置样式
  		this.configureStylesheet();
  		var _this = this;
  		var pasteCount = 0;
  		mxEvent.addListener(options.element,'paste',function(e){
  			var pasteText = e.clipboardData.getData("Text");
  			var doc = mxUtils.parseXml(pasteText);
  			if(doc){
  				var root = doc.documentElement;
  				var dec = new mxCodec(root.ownerDocument);
  				var cells = dec.decode(root);
  				if(cells&&cells.length > 0){
  					pasteCount++;
  					_this.graph.setSelectionCells(_this.graph.importCells(cells, pasteCount * 10, pasteCount * 10, _this.graph.getDefaultParent()));
  				}else{
  					_this.execute('paste');
  				}
  			}else{
  				_this.execute('paste');
  			}
  		});
  		this.keyHandler = new mxKeyHandler(this.graph);
  		this.keyHandler.getFunction = function(evt) {
  			if (evt != null)
  			{
  				return (mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey)) ? this.controlKeys[evt.keyCode] : this.normalKeys[evt.keyCode];
  			}
  			return null;
  		}
  		this.bindKeyAction();
  		var _this = this;
  		//选择节点事件
  		this.graph.getSelectionModel().addListener(mxEvent.CHANGE,function(sender,evt){
  			_this.onSelectedCell(sender,evt);
  		});
  	}
  }
  SpiderEditor.prototype.bindKeyAction = function(){
  	var _this = this;
  	this.keyHandler.bindKey(46,function(){	//按Delete
  		_this.deleteSelectCells();
  	});
  	this.keyHandler.bindControlKey(90,function(){	//Ctrl+Z
  		_this.execute('undo');
  	})
  	this.keyHandler.bindControlKey(89,function(){	//Ctrl+Y
  		_this.execute('redo');
  	})
  	this.keyHandler.bindControlKey(88,function(){ // Ctrl+X
  		_this.execute('cut');
  	});
  	this.keyHandler.bindControlKey(67, function(){	// Ctrl+C
  		_this.executeCopy();
  	});
  	this.keyHandler.bindControlKey(65,function(){	// Ctrl+A
  		editor.execute('selectAll');
  	});
  }
  SpiderEditor.prototype.configureStylesheet = function(){
  	var style = new Object();
  	style = this.graph.getStylesheet().getDefaultEdgeStyle();
  	style[mxConstants.STYLE_EDGE] = mxConstants.EDGESTYLE_ORTHOGONAL;
  	style[mxConstants.STYLE_STROKECOLOR] = 'black';
  	style[mxConstants.STYLE_STROKEWIDTH] = '2';
  	style = this.graph.getStylesheet().getDefaultVertexStyle();
  	style[mxConstants.STYLE_STROKECOLOR] = 'black';
  	style[mxConstants.STYLE_FONTSIZE] = 12;
  	this.graph.alternateEdgeStyle = 'elbow=vertical';
  }
  SpiderEditor.prototype.deleteSelectCells = function(){
  	this.graph.escape();
  	var selectCells = this.graph.getDeletableCells(this.graph.getSelectionCells());
  	if (selectCells != null && selectCells.length > 0){
  		var cells = [];
  		for(var i =0,len = selectCells.length;i<len;i++){
  			var cell = selectCells[i];
  			if((!cell.isVertex())||(cell.data&&cell.data.get('shape') != 'start')){
  				cells.push(cell);
  			}
  		}
  		if(cells.length == 0){
  			return;
  		}
  		var parents = (this.graph.selectParentAfterDelete) ? this.graph.model.getParents(cells) : null;
  		this.graph.removeCells(cells, true);
  		if (parents != null){
  			var select = [];
  			for (var i = 0; i < parents.length; i++){
  				if (this.graph.model.contains(parents[i]) &&
  					(this.graph.model.isVertex(parents[i]) ||
  					this.graph.model.isEdge(parents[i]))){
  					select.push(parents[i]);
  				}
  			}
  			this.graph.setSelectionCells(select);
  		}
  	}
  }
  SpiderEditor.prototype.addShape = function(shape,label,element,defaultAdd){
  	var style = new Object();
  	if(shape == 'comment'){
  		style[mxConstants.STYLE_FILLCOLOR] = 'none';
  		style[mxConstants.STYLE_STROKECOLOR] = 'none';
  	}else{
  		style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE;
  		style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;
  		style[mxConstants.STYLE_IMAGE_WIDTH] = 32;
  		style[mxConstants.STYLE_IMAGE_HEIGHT] = 32;
  		style[mxConstants.STYLE_IMAGE] = element.src;
  		style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
  		style[mxConstants.STYLE_SPACING_TOP] = -26;
  	}
  	style[mxConstants.STYLE_FONTCOLOR] = '#000000';
  	this.graph.getStylesheet().putCellStyle(shape,style);
  	var _this = this;
  	var funct = function(graph, evt, cell, x, y){
  		var parent = _this.graph.getDefaultParent();
  		var model = _this.graph.getModel();
  		model.beginUpdate();
  		var cell;
  		try{
  			cell = _this.graph.insertVertex(parent, null, label, x, y, 32, 32,shape);
  			cell.data = new JsonProperty();
  			cell.data.set('shape',shape);
  		}finally{
  			model.endUpdate();
  		}
  		_this.graph.setSelectionCell(cell);
  	}
  	var dragElt = document.createElement('div');
  	dragElt.style.border = 'dashed black 1px';
  	dragElt.style.width = '32px';
  	dragElt.style.height = '32px';
  	var ds = mxUtils.makeDraggable(element, this.graph, funct, dragElt, 0, 0, true, true);
  	ds.setGuidesEnabled(true);
  	if(defaultAdd){
  		var parent = this.graph.getDefaultParent();
  		var model = this.graph.getModel();
  		model.beginUpdate();
  		try{
  			cell = this.graph.insertVertex(parent, null, label, 80, 80, 32, 32,shape);
  			cell.data = new JsonProperty();
  			cell.data.set('shape',shape);
  		}finally{
  			model.endUpdate();
  		}
  	}
  }
  SpiderEditor.prototype.registerJsonCodec = function(){
  	var codec = new mxObjectCodec(new JsonProperty());
  	codec.encode = function(enc,obj){
  		var node = enc.document.createElement('JsonProperty');
  		mxUtils.setTextContent(node, JSON.stringify(obj.object));
  		return node;
  	}
  	codec.decode = function(dec, node, into){
  		return new JsonProperty(JSON.parse(mxUtils.getTextContent(node)));
  	}
  	mxCodecRegistry.register(codec);
  }
  SpiderEditor.prototype.onSelectedCell = function(sender,evt){
  	this.selectedCellListener(this.getSelectedCell());
  }
  SpiderEditor.prototype.getModel = function(){
  	return this.graph.getModel();
  }
  SpiderEditor.prototype.executeCopy = function(){
  	this.editor.execute('copy');
  	var cells = this.graph.getSelectionCells();
  	if(cells && cells.length > 0){
  		var copyText = document.createElement('textarea');
  		copyText.style = 'position:absolute;left:-99999999px';
  		document.body.appendChild(copyText);
  		copyText.innerHTML = mxUtils.getPrettyXml(new mxCodec().encode(cells));
  		copyText.readOnly = false;
  		copyText.select();
  		copyText.setSelectionRange(0, copyText.value.length);
  		document.execCommand("copy");
  		document.body.removeChild(copyText);
  	}
  }
  SpiderEditor.prototype.execute = function(action){
  	if('copy' == action){
  		this.executeCopy();
  	}else{
  		this.editor.execute(action);
  	}
  }
  SpiderEditor.prototype.getSelectedCell = function(){
  	var cell = this.graph.getSelectionCell() || this.graph.getModel().getRoot();
  	cell.data = cell.data || new JsonProperty();
  	return cell;
  }
  SpiderEditor.prototype.getXML = function(){
  	return mxUtils.getPrettyXml(new mxCodec(mxUtils.createXmlDocument()).encode(this.graph.getModel()));
  }
  SpiderEditor.prototype.selectCell = function(cell){
  	this.graph.setSelectionCell(cell);
  }
  SpiderEditor.prototype.valid = function(){
  	var cells = editor.graph.getModel().cells;
  	for(var key in cells){
  		var cell = cells[key];
  		if(cell&&cell.edge){
  			if(cell.source == null || cell.target == null){
  				return cell;
  			}
  		}
  	}
  	return null;
  }
  SpiderEditor.prototype.setXML = function(xml){
  	var doc = mxUtils.parseXml(xml);
  	var root = doc.documentElement;
  	var dec = new mxCodec(root.ownerDocument);
  	dec.decode(root,this.getModel());
  	this.selectedCellListener(this.getSelectedCell());
  }
  SpiderEditor.prototype.importFromUrl = function(url){
  	var req = mxUtils.load(url);
  	var root = req.getDocumentElement();
  	var dec = new mxCodec(root.ownerDocument);
  	dec.decode(root, this.getModel());
  }