You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
6.8 KiB
255 lines
6.8 KiB
/*global kampfer*/
|
|
kampfer.require('Class');
|
|
|
|
kampfer.provide('mindMap.MapManager');
|
|
|
|
/*
|
|
* MapManager类为mindmap提供数据支持。
|
|
* 注意:1.MapManager依赖的第三方组件store.js依赖JSON,当浏览器不原生支持JSON时,
|
|
* 需要额外引入JSON.js实现兼容。
|
|
* 2.MapManager提供的查询方法返回的都是对数据的引用,因此它们都是只读的,绝对不要直接
|
|
* 对它们进行写操作。
|
|
*/
|
|
|
|
kampfer.mindMap.MapManager = kampfer.Class.extend({
|
|
|
|
/**
|
|
* 实例化一个MapManager对象。
|
|
* 当传递给构建函数的参数是一个对象,那么这个对象被用作mindmap数据来源
|
|
* @param name{string|object|null}
|
|
*/
|
|
initializer : function(data) {
|
|
this._oriData = data;
|
|
|
|
data = data || {};
|
|
this._nodeTree = data.document || [];
|
|
this._mapName = data.name;
|
|
this._lastModified = data.lastModified || +new Date();
|
|
//map用于快速查找
|
|
this._nodeMap = this.parseTree(this._nodeTree);
|
|
this._isModified = false;
|
|
},
|
|
|
|
_isModified : null,
|
|
|
|
//重命名map的时候先改变_mapName.保存时会检查_mapName和_mapData.name的一致性,
|
|
//两者如果不一致那么会删除localstore中名字叫_mapData.name的数据.并将_mapName
|
|
//和_mapData.name同步. 这个过程需要同时保存新名字和旧名字,_mapName保存新名字
|
|
//_mapData.name是旧名字。
|
|
_mapName : null,
|
|
|
|
//解析原始数据, 通过tree生成map
|
|
parseTree : function(data) {
|
|
var map = {};
|
|
|
|
for(var i = 0, root; (root = data[i]); i++) {
|
|
this.traverseNode(root, function(node) {
|
|
map[node.id] = node;
|
|
});
|
|
}
|
|
|
|
return map;
|
|
},
|
|
|
|
isModified : function() {
|
|
return this._isModified;
|
|
},
|
|
|
|
getMapName : function() {
|
|
return this._mapName;
|
|
},
|
|
|
|
getNode : function(id) {
|
|
return this._nodeMap[id];
|
|
},
|
|
|
|
getChildren : function(id) {
|
|
if(id) {
|
|
var node = this.getNode(id);
|
|
return node.children;
|
|
}
|
|
},
|
|
|
|
getNodeTree : function() {
|
|
return this._nodeTree;
|
|
},
|
|
|
|
//如果有同id的node那么新的node不会被添加
|
|
addNode : function(node) {
|
|
if( kampfer.type(node) === 'object' && !this.getNode(node.id) ) {
|
|
var parent = this.getNode(node.parent);
|
|
|
|
//add node to nodeTree
|
|
if(parent) {
|
|
if(!parent.children) {
|
|
parent.children = [];
|
|
}
|
|
parent.children.push(node);
|
|
} else {
|
|
this._nodeTree.push(node);
|
|
}
|
|
|
|
//保存node和它的子节点的引用
|
|
this.traverseNode(node, function(node) {
|
|
if( !(node.id in this._nodeMap) ) {
|
|
this._nodeMap[node.id] = node;
|
|
}
|
|
});
|
|
|
|
this._isModified = true;
|
|
}
|
|
},
|
|
|
|
createNode : function(data) {
|
|
var node = {
|
|
id : this.generateUniqueId(),
|
|
parent : null,
|
|
children : null,
|
|
content : 'node',
|
|
offset : {
|
|
x : 100,
|
|
y : 100
|
|
}
|
|
},
|
|
type = kampfer.type(data);
|
|
|
|
if( type === 'object' ) {
|
|
for(var attr in node) {
|
|
if(attr in data) {
|
|
if(attr === 'offset') {
|
|
node[attr].x = data[attr].x;
|
|
node[attr].y = data[attr].y;
|
|
} else {
|
|
node[attr] = data[attr];
|
|
}
|
|
}
|
|
}
|
|
} else if( type === 'string' ) {
|
|
node.parent = data;
|
|
}
|
|
|
|
return node;
|
|
},
|
|
|
|
//此方法会立即改变children数组的长度
|
|
deleteNode : function(id) {
|
|
var node = this.getNode(id), parent, nodeList;
|
|
|
|
if(!node) {
|
|
return;
|
|
}
|
|
|
|
parent = this.getNode(node.parent);
|
|
if(!parent) {
|
|
nodeList = this._nodeTree;
|
|
} else if(parent.children) {
|
|
nodeList = parent.children;
|
|
}
|
|
if(nodeList) {
|
|
//delete node from tree
|
|
for(var i = 0, c; (c = nodeList[i]); i++) {
|
|
if(c.id === id) {
|
|
nodeList.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//delete node from map
|
|
this.traverseNode(node, function(node) {
|
|
delete this._nodeMap[node.id];
|
|
});
|
|
|
|
this._isModified = true;
|
|
|
|
return node;
|
|
},
|
|
|
|
setNodeContent : function(id, text) {
|
|
var node = this.getNode(id);
|
|
node.content = text;
|
|
this._isModified = true;
|
|
},
|
|
|
|
getNodeContent : function(id) {
|
|
var node = this.getNode(id);
|
|
return node.content;
|
|
},
|
|
|
|
setNodePosition : function(id, x, y) {
|
|
if(kampfer.type(id) === 'object') {
|
|
id = id.id;
|
|
}
|
|
var node = this.getNode(id);
|
|
node.offset.x = x;
|
|
node.offset.y = y;
|
|
this._isModified = true;
|
|
},
|
|
|
|
//传值
|
|
getNodePosition : function(id) {
|
|
var node = this.getNode(id);
|
|
return {
|
|
left : node.offset.x,
|
|
top : node.offset.y
|
|
};
|
|
},
|
|
|
|
setMapName : function(name) {
|
|
this._mapName = name;
|
|
this._isModified = true;
|
|
},
|
|
|
|
getMapData : function() {
|
|
return {
|
|
document : this._nodeTree,
|
|
name : this._mapName,
|
|
lastModified : this._lastModified
|
|
};
|
|
},
|
|
|
|
traverseNode : function(node, callback, forward) {
|
|
if(forward) {
|
|
callback.call(this, node);
|
|
}
|
|
if(node.children) {
|
|
for(var i = 0, child; (child = node.children[i]); i++) {
|
|
this.traverseNode(child, callback, forward);
|
|
}
|
|
}
|
|
if(!forward) {
|
|
callback.call(this, node);
|
|
}
|
|
},
|
|
|
|
traverse : function(callback) {
|
|
for(var i = 0, node; (node = this._nodeTree[i]); i++) {
|
|
this.traverseNode(node, callback, true);
|
|
}
|
|
},
|
|
|
|
/*
|
|
* 生成唯一id
|
|
* 直接使用时间戳不可行
|
|
* 以下方法摘自http://www.cnblogs.com/NoRoad/archive/2010/03/12/1684759.html
|
|
*/
|
|
generateUniqueId : function() {
|
|
var guid = "";
|
|
for(var i = 1; i <= 32; i++) {
|
|
var n = Math.floor(Math.random() * 16.0).toString(16);
|
|
guid += n;
|
|
if((i == 8) || (i == 12) || (i == 16) || (i == 20)) {
|
|
guid += "-";
|
|
}
|
|
}
|
|
return guid;
|
|
},
|
|
|
|
dispose : function() {
|
|
delete this._oriData;
|
|
delete this._nodeTree;
|
|
delete this._mapName;
|
|
delete this._lastModified;
|
|
delete this._nodeMap;
|
|
delete this._isModified;
|
|
}
|
|
}); |