| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- define(function(require, exports, module) {
- var kity = require('./kity');
- var utils = require('./utils');
- var Minder = require('./minder');
- /**
- * @class MinderNode
- *
- * 表示一个脑图节点
- */
- var MinderNode = kity.createClass('MinderNode', {
- /**
- * 创建一个游离的脑图节点
- *
- * @param {String|Object} textOrData
- * 节点的初始数据或文本
- */
- constructor: function(textOrData) {
- // 指针
- this.parent = null;
- this.root = this;
- this.children = [];
- // 数据
- this.data = {
- id: utils.guid(),
- created: +new Date()
- };
- // 绘图容器
- this.initContainers();
- if (utils.isString(textOrData)) {
- this.setText(textOrData);
- } else if (utils.isObject(textOrData)) {
- utils.extend(this.data, textOrData);
- }
- },
- initContainers: function() {
- this.rc = new kity.Group().setId(utils.uuid('minder_node'));
- this.rc.minderNode = this;
- },
- /**
- * 判断节点是否根节点
- */
- isRoot: function() {
- return this.root === this;
- },
- /**
- * 判断节点是否叶子
- */
- isLeaf: function() {
- return this.children.length === 0;
- },
- /**
- * 获取节点的根节点
- */
- getRoot: function() {
- return this.root || this;
- },
- /**
- * 获得节点的父节点
- */
- getParent: function() {
- return this.parent;
- },
- getSiblings: function() {
- var children = this.parent.children;
- var siblings = [];
- var self = this;
- children.forEach(function(child) {
- if (child != self) siblings.push(child);
- });
- return siblings;
- },
- /**
- * 获得节点的深度
- */
- getLevel: function() {
- var level = 0,
- ancestor = this.parent;
- while (ancestor) {
- level++;
- ancestor = ancestor.parent;
- }
- return level;
- },
- /**
- * 获得节点的复杂度(即子树中节点的数量)
- */
- getComplex: function() {
- var complex = 0;
- this.traverse(function() {
- complex++;
- });
- return complex;
- },
- /**
- * 获得节点的类型(root|main|sub)
- */
- getType: function(type) {
- this.type = ['root', 'main', 'sub'][Math.min(this.getLevel(), 2)];
- return this.type;
- },
- /**
- * 判断当前节点是否被测试节点的祖先
- * @param {MinderNode} test 被测试的节点
- */
- isAncestorOf: function(test) {
- var ancestor = test.parent;
- while (ancestor) {
- if (ancestor == this) return true;
- ancestor = ancestor.parent;
- }
- return false;
- },
- getData: function(key) {
- return key ? this.data[key] : this.data;
- },
- setData: function(key, value) {
- if (typeof key == 'object') {
- var data = key;
- for (key in data) if (data.hasOwnProperty(key)) {
- this.data[key] = data[key];
- }
- }
- else {
- this.data[key] = value;
- }
- return this;
- },
- /**
- * 设置节点的文本数据
- * @param {String} text 文本数据
- */
- setText: function(text) {
- return this.data.text = text;
- },
- /**
- * 获取节点的文本数据
- * @return {String}
- */
- getText: function() {
- return this.data.text || null;
- },
- /**
- * 先序遍历当前节点树
- * @param {Function} fn 遍历函数
- */
- preTraverse: function(fn, excludeThis) {
- var children = this.getChildren();
- if (!excludeThis) fn(this);
- for (var i = 0; i < children.length; i++) {
- children[i].preTraverse(fn);
- }
- },
- /**
- * 后序遍历当前节点树
- * @param {Function} fn 遍历函数
- */
- postTraverse: function(fn, excludeThis) {
- var children = this.getChildren();
- for (var i = 0; i < children.length; i++) {
- children[i].postTraverse(fn);
- }
- if (!excludeThis) fn(this);
- },
- traverse: function(fn, excludeThis) {
- return this.postTraverse(fn, excludeThis);
- },
- getChildren: function() {
- return this.children;
- },
- getIndex: function() {
- return this.parent ? this.parent.children.indexOf(this) : -1;
- },
- insertChild: function(node, index) {
- if (index === undefined) {
- index = this.children.length;
- }
- if (node.parent) {
- node.parent.removeChild(node);
- }
- node.parent = this;
- node.root = this.root;
- this.children.splice(index, 0, node);
- },
- appendChild: function(node) {
- return this.insertChild(node);
- },
- prependChild: function(node) {
- return this.insertChild(node, 0);
- },
- removeChild: function(elem) {
- var index = elem,
- removed;
- if (elem instanceof MinderNode) {
- index = this.children.indexOf(elem);
- }
- if (index >= 0) {
- removed = this.children.splice(index, 1)[0];
- removed.parent = null;
- removed.root = removed;
- }
- },
- clearChildren: function() {
- this.children = [];
- },
- getChild: function(index) {
- return this.children[index];
- },
- getRenderContainer: function() {
- return this.rc;
- },
- getCommonAncestor: function(node) {
- return MinderNode.getCommonAncestor(this, node);
- },
- contains: function(node) {
- return this == node || this.isAncestorOf(node);
- },
- clone: function() {
- var cloned = new MinderNode();
- cloned.data = utils.clone(this.data);
- this.children.forEach(function(child) {
- cloned.appendChild(child.clone());
- });
- return cloned;
- },
- compareTo: function(node) {
- if (!utils.comparePlainObject(this.data, node.data)) return false;
- if (!utils.comparePlainObject(this.temp, node.temp)) return false;
- if (this.children.length != node.children.length) return false;
- var i = 0;
- while (this.children[i]) {
- if (!this.children[i].compareTo(node.children[i])) return false;
- i++;
- }
- return true;
- },
- getMinder: function() {
- return this.getRoot().minder;
- }
- });
- MinderNode.getCommonAncestor = function(nodeA, nodeB) {
- if (nodeA instanceof Array) {
- return MinderNode.getCommonAncestor.apply(this, nodeA);
- }
- switch (arguments.length) {
- case 1:
- return nodeA.parent || nodeA;
- case 2:
- if (nodeA.isAncestorOf(nodeB)) {
- return nodeA;
- }
- if (nodeB.isAncestorOf(nodeA)) {
- return nodeB;
- }
- var ancestor = nodeA.parent;
- while (ancestor && !ancestor.isAncestorOf(nodeB)) {
- ancestor = ancestor.parent;
- }
- return ancestor;
- default:
- return Array.prototype.reduce.call(arguments,
- function(prev, current) {
- return MinderNode.getCommonAncestor(prev, current);
- },
- nodeA
- );
- }
- };
- kity.extendClass(Minder, {
- getRoot: function() {
- return this._root;
- },
- setRoot: function(root) {
- this._root = root;
- root.minder = this;
- },
- getAllNode: function() {
- var nodes = [];
- this.getRoot().traverse(function(node) {
- nodes.push(node);
- });
- return nodes;
- },
- getNodeById: function(id) {
- return this.getNodesById([id])[0];
- },
- getNodesById: function(ids) {
- var nodes = this.getAllNode();
- var result = [];
- nodes.forEach(function(node) {
- if (ids.indexOf(node.getData('id')) != -1) {
- result.push(node);
- }
- });
- return result;
- },
- createNode: function(textOrData, parent, index) {
- var node = new MinderNode(textOrData);
- this.fire('nodecreate', {
- node: node,
- parent: parent,
- index: index
- });
- this.appendNode(node, parent, index);
- return node;
- },
- appendNode: function(node, parent, index) {
- if (parent) parent.insertChild(node, index);
- this.attachNode(node);
- return this;
- },
- removeNode: function(node) {
- if (node.parent) {
- node.parent.removeChild(node);
- this.detachNode(node);
- this.fire('noderemove', {
- node: node
- });
- }
- },
- attachNode: function(node) {
- var rc = this.getRenderContainer();
- node.traverse(function(current) {
- current.attached = true;
- rc.addShape(current.getRenderContainer());
- });
- rc.addShape(node.getRenderContainer());
- this.fire('nodeattach', {
- node: node
- });
- },
- detachNode: function(node) {
- var rc = this.getRenderContainer();
- node.traverse(function(current) {
- current.attached = false;
- rc.removeShape(current.getRenderContainer());
- });
- this.fire('nodedetach', {
- node: node
- });
- },
- getMinderTitle: function() {
- return this.getRoot().getText();
- }
- });
- module.exports = MinderNode;
- });
|