255 lines
6.8 KiB
JavaScript
255 lines
6.8 KiB
JavaScript
/*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;
|
||
}
|
||
}); |