1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | ; (function ($w) {
|
10 | 'use strict';
|
11 | console.warn("The version is outdated. see details: https://hizzgdev.github.io/jsmind/es6/")
|
12 |
|
13 |
|
14 | var __name__ = 'jsMind';
|
15 |
|
16 | var __version__ = '0.5.7';
|
17 |
|
18 | var __author__ = 'hizzgdev@163.com';
|
19 |
|
20 |
|
21 | var _noop = function () { };
|
22 | var logger = (typeof console === 'undefined') ? {
|
23 | log: _noop, debug: _noop, error: _noop, warn: _noop, info: _noop
|
24 | } : console;
|
25 |
|
26 |
|
27 | if (typeof module === 'undefined' || !module.exports) {
|
28 | if (typeof $w[__name__] != 'undefined') {
|
29 | logger.log(__name__ + ' has been already exist.');
|
30 | return;
|
31 | }
|
32 | }
|
33 |
|
34 |
|
35 | var $d = $w.document;
|
36 | var $g = function (id) { return $d.getElementById(id); };
|
37 | var $c = function (tag) { return $d.createElement(tag); };
|
38 | var $t = function (n, t) { if (n.hasChildNodes()) { n.firstChild.nodeValue = t; } else { n.appendChild($d.createTextNode(t)); } };
|
39 |
|
40 | var $h = function (n, t) {
|
41 | if (t instanceof HTMLElement) {
|
42 | n.innerHTML = '';
|
43 | n.appendChild(t);
|
44 | } else {
|
45 | n.innerHTML = t;
|
46 | }
|
47 | };
|
48 |
|
49 | var $i = function (el) { return !!el && (typeof el === 'object') && (el.nodeType === 1) && (typeof el.style === 'object') && (typeof el.ownerDocument === 'object'); };
|
50 | if (typeof String.prototype.startsWith != 'function') { String.prototype.startsWith = function (p) { return this.slice(0, p.length) === p; }; }
|
51 |
|
52 | var DEFAULT_OPTIONS = {
|
53 | container: '',
|
54 | editable: false,
|
55 | theme: null,
|
56 | mode: 'full',
|
57 | support_html: true,
|
58 |
|
59 | view: {
|
60 | engine: 'canvas',
|
61 | hmargin: 100,
|
62 | vmargin: 50,
|
63 | line_width: 2,
|
64 | line_color: '#555',
|
65 | draggable: false,
|
66 | hide_scrollbars_when_draggable: false,
|
67 | node_overflow: 'hidden'
|
68 | },
|
69 | layout: {
|
70 | hspace: 30,
|
71 | vspace: 20,
|
72 | pspace: 13,
|
73 | cousin_space: 0
|
74 | },
|
75 | default_event_handle: {
|
76 | enable_mousedown_handle: true,
|
77 | enable_click_handle: true,
|
78 | enable_dblclick_handle: true,
|
79 | enable_mousewheel_handle: true
|
80 | },
|
81 | shortcut: {
|
82 | enable: true,
|
83 | handles: {
|
84 | },
|
85 | mapping: {
|
86 | addchild: [45, 4096+13],
|
87 | addbrother: 13,
|
88 | editnode: 113,
|
89 | delnode: 46,
|
90 | toggle: 32,
|
91 | left: 37,
|
92 | up: 38,
|
93 | right: 39,
|
94 | down: 40,
|
95 | }
|
96 | },
|
97 | };
|
98 |
|
99 |
|
100 | var jm = function (options) {
|
101 | jm.current = this;
|
102 |
|
103 | this.version = __version__;
|
104 | var opts = {};
|
105 | jm.util.json.merge(opts, DEFAULT_OPTIONS);
|
106 | jm.util.json.merge(opts, options);
|
107 |
|
108 | if (!opts.container) {
|
109 | logger.error('the options.container should not be null or empty.');
|
110 | return;
|
111 | }
|
112 | this.options = opts;
|
113 | this.initialized = false;
|
114 | this.mind = null;
|
115 | this.event_handles = [];
|
116 | this.init();
|
117 | };
|
118 |
|
119 |
|
120 | jm.direction = {
|
121 | left: -1, center: 0, right: 1, of: function (dir) {
|
122 | if (!dir || dir === -1 || dir === 0 || dir === 1) {
|
123 | return dir;
|
124 | }
|
125 | if (dir === '-1' || dir === '0' || dir === '1') {
|
126 | return parseInt(dir);
|
127 | }
|
128 | if (dir.toLowerCase() === 'left') {
|
129 | return this.left;
|
130 | }
|
131 | if (dir.toLowerCase() === 'right') {
|
132 | return this.right;
|
133 | }
|
134 | if (dir.toLowerCase() === 'center') {
|
135 | return this.center;
|
136 | }
|
137 | }
|
138 | };
|
139 | jm.event_type = { show: 1, resize: 2, edit: 3, select: 4 };
|
140 | jm.key = { meta: 1 << 13, ctrl: 1 << 12, alt: 1 << 11, shift: 1 << 10 };
|
141 |
|
142 | jm.node = function (sId, iIndex, sTopic, oData, bIsRoot, oParent, eDirection, bExpanded) {
|
143 | if (!sId) { logger.error('invalid node id'); return; }
|
144 | if (typeof iIndex != 'number') { logger.error('invalid node index'); return; }
|
145 | if (typeof bExpanded === 'undefined') { bExpanded = true; }
|
146 | this.id = sId;
|
147 | this.index = iIndex;
|
148 | this.topic = sTopic;
|
149 | this.data = oData || {};
|
150 | this.isroot = bIsRoot;
|
151 | this.parent = oParent;
|
152 | this.direction = eDirection;
|
153 | this.expanded = !!bExpanded;
|
154 | this.children = [];
|
155 | this._data = {};
|
156 | };
|
157 |
|
158 | jm.node.compare = function (node1, node2) {
|
159 |
|
160 | var r = 0;
|
161 | var i1 = node1.index;
|
162 | var i2 = node2.index;
|
163 | if (i1 >= 0 && i2 >= 0) {
|
164 | r = i1 - i2;
|
165 | } else if (i1 == -1 && i2 == -1) {
|
166 | r = 0;
|
167 | } else if (i1 == -1) {
|
168 | r = 1;
|
169 | } else if (i2 == -1) {
|
170 | r = -1;
|
171 | } else {
|
172 | r = 0;
|
173 | }
|
174 |
|
175 | return r;
|
176 | };
|
177 |
|
178 | jm.node.inherited = function (pnode, node) {
|
179 | if (!!pnode && !!node) {
|
180 | if (pnode.id === node.id) {
|
181 | return true;
|
182 | }
|
183 | if (pnode.isroot) {
|
184 | return true;
|
185 | }
|
186 | var pid = pnode.id;
|
187 | var p = node;
|
188 | while (!p.isroot) {
|
189 | p = p.parent;
|
190 | if (p.id === pid) {
|
191 | return true;
|
192 | }
|
193 | }
|
194 | }
|
195 | return false;
|
196 | };
|
197 |
|
198 | jm.node.is_node = function (n) {
|
199 | return !!n && n instanceof jm.node;
|
200 | };
|
201 |
|
202 | jm.node.prototype = {
|
203 | get_location: function () {
|
204 | var vd = this._data.view;
|
205 | return {
|
206 | x: vd.abs_x,
|
207 | y: vd.abs_y
|
208 | };
|
209 | },
|
210 | get_size: function () {
|
211 | var vd = this._data.view;
|
212 | return {
|
213 | w: vd.width,
|
214 | h: vd.height
|
215 | }
|
216 | }
|
217 | };
|
218 |
|
219 |
|
220 | jm.mind = function () {
|
221 | this.name = null;
|
222 | this.author = null;
|
223 | this.version = null;
|
224 | this.root = null;
|
225 | this.selected = null;
|
226 | this.nodes = {};
|
227 | };
|
228 |
|
229 | jm.mind.prototype = {
|
230 | get_node: function (nodeid) {
|
231 | if (nodeid in this.nodes) {
|
232 | return this.nodes[nodeid];
|
233 | } else {
|
234 | logger.warn('the node[id=' + nodeid + '] can not be found');
|
235 | return null;
|
236 | }
|
237 | },
|
238 |
|
239 | set_root: function (nodeid, topic, data) {
|
240 | if (this.root == null) {
|
241 | this.root = new jm.node(nodeid, 0, topic, data, true);
|
242 | this._put_node(this.root);
|
243 | return this.root;
|
244 | } else {
|
245 | logger.error('root node is already exist');
|
246 | return null;
|
247 | }
|
248 | },
|
249 |
|
250 | add_node: function (parent_node, nodeid, topic, data, direction, expanded, idx) {
|
251 | if (!jm.util.is_node(parent_node)) {
|
252 | logger.error('the parent_node ' + parent_node + ' is not a node.');
|
253 | return null;
|
254 | }
|
255 | var node_index = idx || -1;
|
256 | var node = new jm.node(nodeid, node_index, topic, data, false, parent_node, parent_node.direction, expanded);
|
257 | if (parent_node.isroot) {
|
258 | node.direction = direction || jm.direction.right;
|
259 | }
|
260 | if (this._put_node(node)) {
|
261 | parent_node.children.push(node);
|
262 | this._reindex(parent_node);
|
263 | } else {
|
264 | logger.error('fail, the nodeid \'' + node.id + '\' has been already exist.');
|
265 | node = null;
|
266 | }
|
267 | return node;
|
268 | },
|
269 |
|
270 | insert_node_before: function (node_before, nodeid, topic, data, direction) {
|
271 | if (!jm.util.is_node(node_before)) {
|
272 | logger.error('the node_before ' + node_before + ' is not a node.');
|
273 | return null;
|
274 | }
|
275 | var node_index = node_before.index - 0.5;
|
276 | return this.add_node(node_before.parent, nodeid, topic, data, direction, true, node_index);
|
277 | },
|
278 |
|
279 | get_node_before: function (node) {
|
280 | if (!jm.util.is_node(node)) {
|
281 | var the_node = this.get_node(node);
|
282 | if (!the_node) {
|
283 | logger.error('the node[id=' + node + '] can not be found.');
|
284 | return null;
|
285 | } else {
|
286 | return this.get_node_before(the_node);
|
287 | }
|
288 | }
|
289 | if (node.isroot) { return null; }
|
290 | var idx = node.index - 2;
|
291 | if (idx >= 0) {
|
292 | return node.parent.children[idx];
|
293 | } else {
|
294 | return null;
|
295 | }
|
296 | },
|
297 |
|
298 | insert_node_after: function (node_after, nodeid, topic, data, direction) {
|
299 | if (!jm.util.is_node(node_after)) {
|
300 | logger.error('the node_after ' + node_after + ' is not a node.');
|
301 | return null;
|
302 | }
|
303 | var node_index = node_after.index + 0.5;
|
304 | return this.add_node(node_after.parent, nodeid, topic, data, direction, true, node_index);
|
305 | },
|
306 |
|
307 | get_node_after: function (node) {
|
308 | if (!jm.util.is_node(node)) {
|
309 | var the_node = this.get_node(node);
|
310 | if (!the_node) {
|
311 | logger.error('the node[id=' + node + '] can not be found.');
|
312 | return null;
|
313 | } else {
|
314 | return this.get_node_after(the_node);
|
315 | }
|
316 | }
|
317 | if (node.isroot) { return null; }
|
318 | var idx = node.index;
|
319 | var brothers = node.parent.children;
|
320 | if (brothers.length > idx) {
|
321 | return node.parent.children[idx];
|
322 | } else {
|
323 | return null;
|
324 | }
|
325 | },
|
326 |
|
327 | move_node: function (node, before_id, parent_id, direction) {
|
328 | if (!jm.util.is_node(node)) {
|
329 | logger.error('the parameter node ' + node + ' is not a node.');
|
330 | return null;
|
331 | }
|
332 | if (!parent_id) {
|
333 | parent_id = node.parent.id;
|
334 | }
|
335 | return this._move_node(node, before_id, parent_id, direction);
|
336 | },
|
337 |
|
338 | _flow_node_direction: function (node, direction) {
|
339 | if (typeof direction === 'undefined') {
|
340 | direction = node.direction;
|
341 | } else {
|
342 | node.direction = direction;
|
343 | }
|
344 | var len = node.children.length;
|
345 | while (len--) {
|
346 | this._flow_node_direction(node.children[len], direction);
|
347 | }
|
348 | },
|
349 |
|
350 | _move_node_internal: function (node, beforeid) {
|
351 | if (!!node && !!beforeid) {
|
352 | if (beforeid == '_last_') {
|
353 | node.index = -1;
|
354 | this._reindex(node.parent);
|
355 | } else if (beforeid == '_first_') {
|
356 | node.index = 0;
|
357 | this._reindex(node.parent);
|
358 | } else {
|
359 | var node_before = (!!beforeid) ? this.get_node(beforeid) : null;
|
360 | if (node_before != null && node_before.parent != null && node_before.parent.id == node.parent.id) {
|
361 | node.index = node_before.index - 0.5;
|
362 | this._reindex(node.parent);
|
363 | }
|
364 | }
|
365 | }
|
366 | return node;
|
367 | },
|
368 |
|
369 | _move_node: function (node, beforeid, parentid, direction) {
|
370 | if (!!node && !!parentid) {
|
371 | var parent_node = this.get_node(parentid)
|
372 | if (jm.node.inherited(node, parent_node)) {
|
373 | logger.error('can not move a node to its children');
|
374 | return null;
|
375 | }
|
376 | if (node.parent.id != parentid) {
|
377 |
|
378 | var sibling = node.parent.children;
|
379 | var si = sibling.length;
|
380 | while (si--) {
|
381 | if (sibling[si].id == node.id) {
|
382 | sibling.splice(si, 1);
|
383 | break;
|
384 | }
|
385 | }
|
386 | node.parent = parent_node;
|
387 | parent_node.children.push(node);
|
388 | }
|
389 |
|
390 | if (node.parent.isroot) {
|
391 | if (direction == jm.direction.left) {
|
392 | node.direction = direction;
|
393 | } else {
|
394 | node.direction = jm.direction.right;
|
395 | }
|
396 | } else {
|
397 | node.direction = node.parent.direction;
|
398 | }
|
399 | this._move_node_internal(node, beforeid);
|
400 | this._flow_node_direction(node);
|
401 | }
|
402 | return node;
|
403 | },
|
404 |
|
405 | remove_node: function (node) {
|
406 | if (!jm.util.is_node(node)) {
|
407 | logger.error('the parameter node ' + node + ' is not a node.');
|
408 | return false;
|
409 | }
|
410 | if (node.isroot) {
|
411 | logger.error('fail, can not remove root node');
|
412 | return false;
|
413 | }
|
414 | if (this.selected != null && this.selected.id == node.id) {
|
415 | this.selected = null;
|
416 | }
|
417 |
|
418 | var children = node.children;
|
419 | var ci = children.length;
|
420 | while (ci--) {
|
421 | this.remove_node(children[ci]);
|
422 | }
|
423 |
|
424 | children.length = 0;
|
425 |
|
426 | var sibling = node.parent.children;
|
427 | var si = sibling.length;
|
428 | while (si--) {
|
429 | if (sibling[si].id == node.id) {
|
430 | sibling.splice(si, 1);
|
431 | break;
|
432 | }
|
433 | }
|
434 |
|
435 | delete this.nodes[node.id];
|
436 |
|
437 | for (var k in node) {
|
438 | delete node[k];
|
439 | }
|
440 |
|
441 | node = null;
|
442 |
|
443 | return true;
|
444 | },
|
445 |
|
446 | _put_node: function (node) {
|
447 | if (node.id in this.nodes) {
|
448 | logger.warn('the nodeid \'' + node.id + '\' has been already exist.');
|
449 | return false;
|
450 | } else {
|
451 | this.nodes[node.id] = node;
|
452 | return true;
|
453 | }
|
454 | },
|
455 |
|
456 | _reindex: function (node) {
|
457 | if (node instanceof jm.node) {
|
458 | node.children.sort(jm.node.compare);
|
459 | for (var i = 0; i < node.children.length; i++) {
|
460 | node.children[i].index = i + 1;
|
461 | }
|
462 | }
|
463 | },
|
464 | };
|
465 |
|
466 | jm.format = {
|
467 | node_tree: {
|
468 | example: {
|
469 | "meta": {
|
470 | "name": __name__,
|
471 | "author": __author__,
|
472 | "version": __version__
|
473 | },
|
474 | "format": "node_tree",
|
475 | "data": { "id": "root", "topic": "jsMind Example" }
|
476 | },
|
477 | get_mind: function (source) {
|
478 | var df = jm.format.node_tree;
|
479 | var mind = new jm.mind();
|
480 | mind.name = source.meta.name;
|
481 | mind.author = source.meta.author;
|
482 | mind.version = source.meta.version;
|
483 | df._parse(mind, source.data);
|
484 | return mind;
|
485 | },
|
486 | get_data: function (mind) {
|
487 | var df = jm.format.node_tree;
|
488 | var json = {};
|
489 | json.meta = {
|
490 | name: mind.name,
|
491 | author: mind.author,
|
492 | version: mind.version
|
493 | };
|
494 | json.format = 'node_tree';
|
495 | json.data = df._buildnode(mind.root);
|
496 | return json;
|
497 | },
|
498 |
|
499 | _parse: function (mind, node_root) {
|
500 | var df = jm.format.node_tree;
|
501 | var data = df._extract_data(node_root);
|
502 | mind.set_root(node_root.id, node_root.topic, data);
|
503 | if ('children' in node_root) {
|
504 | var children = node_root.children;
|
505 | for (var i = 0; i < children.length; i++) {
|
506 | df._extract_subnode(mind, mind.root, children[i]);
|
507 | }
|
508 | }
|
509 | },
|
510 |
|
511 | _extract_data: function (node_json) {
|
512 | var data = {};
|
513 | for (var k in node_json) {
|
514 | if (k == 'id' || k == 'topic' || k == 'children' || k == 'direction' || k == 'expanded') {
|
515 | continue;
|
516 | }
|
517 | data[k] = node_json[k];
|
518 | }
|
519 | return data;
|
520 | },
|
521 |
|
522 | _extract_subnode: function (mind, node_parent, node_json) {
|
523 | var df = jm.format.node_tree;
|
524 | var data = df._extract_data(node_json);
|
525 | var d = null;
|
526 | if (node_parent.isroot) {
|
527 | d = node_json.direction == 'left' ? jm.direction.left : jm.direction.right;
|
528 | }
|
529 | var node = mind.add_node(node_parent, node_json.id, node_json.topic, data, d, node_json.expanded);
|
530 | if (!!node_json['children']) {
|
531 | var children = node_json.children;
|
532 | for (var i = 0; i < children.length; i++) {
|
533 | df._extract_subnode(mind, node, children[i]);
|
534 | }
|
535 | }
|
536 | },
|
537 |
|
538 | _buildnode: function (node) {
|
539 | var df = jm.format.node_tree;
|
540 | if (!(node instanceof jm.node)) { return; }
|
541 | var o = {
|
542 | id: node.id,
|
543 | topic: node.topic,
|
544 | expanded: node.expanded
|
545 | };
|
546 | if (!!node.parent && node.parent.isroot) {
|
547 | o.direction = node.direction == jm.direction.left ? 'left' : 'right';
|
548 | }
|
549 | if (node.data != null) {
|
550 | var node_data = node.data;
|
551 | for (var k in node_data) {
|
552 | o[k] = node_data[k];
|
553 | }
|
554 | }
|
555 | var children = node.children;
|
556 | if (children.length > 0) {
|
557 | o.children = [];
|
558 | for (var i = 0; i < children.length; i++) {
|
559 | o.children.push(df._buildnode(children[i]));
|
560 | }
|
561 | }
|
562 | return o;
|
563 | }
|
564 | },
|
565 |
|
566 | node_array: {
|
567 | example: {
|
568 | "meta": {
|
569 | "name": __name__,
|
570 | "author": __author__,
|
571 | "version": __version__
|
572 | },
|
573 | "format": "node_array",
|
574 | "data": [
|
575 | { "id": "root", "topic": "jsMind Example", "isroot": true }
|
576 | ]
|
577 | },
|
578 |
|
579 | get_mind: function (source) {
|
580 | var df = jm.format.node_array;
|
581 | var mind = new jm.mind();
|
582 | mind.name = source.meta.name;
|
583 | mind.author = source.meta.author;
|
584 | mind.version = source.meta.version;
|
585 | df._parse(mind, source.data);
|
586 | return mind;
|
587 | },
|
588 |
|
589 | get_data: function (mind) {
|
590 | var df = jm.format.node_array;
|
591 | var json = {};
|
592 | json.meta = {
|
593 | name: mind.name,
|
594 | author: mind.author,
|
595 | version: mind.version
|
596 | };
|
597 | json.format = 'node_array';
|
598 | json.data = [];
|
599 | df._array(mind, json.data);
|
600 | return json;
|
601 | },
|
602 |
|
603 | _parse: function (mind, node_array) {
|
604 | var df = jm.format.node_array;
|
605 | var narray = node_array.slice(0);
|
606 |
|
607 | narray.reverse();
|
608 | var root_node = df._extract_root(mind, narray);
|
609 | if (!!root_node) {
|
610 | df._extract_subnode(mind, root_node, narray);
|
611 | } else {
|
612 | logger.error('root node can not be found');
|
613 | }
|
614 | },
|
615 |
|
616 | _extract_root: function (mind, node_array) {
|
617 | var df = jm.format.node_array;
|
618 | var i = node_array.length;
|
619 | while (i--) {
|
620 | if ('isroot' in node_array[i] && node_array[i].isroot) {
|
621 | var root_json = node_array[i];
|
622 | var data = df._extract_data(root_json);
|
623 | var node = mind.set_root(root_json.id, root_json.topic, data);
|
624 | node_array.splice(i, 1);
|
625 | return node;
|
626 | }
|
627 | }
|
628 | return null;
|
629 | },
|
630 |
|
631 | _extract_subnode: function (mind, parent_node, node_array) {
|
632 | var df = jm.format.node_array;
|
633 | var i = node_array.length;
|
634 | var node_json = null;
|
635 | var data = null;
|
636 | var extract_count = 0;
|
637 | while (i--) {
|
638 | node_json = node_array[i];
|
639 | if (node_json.parentid == parent_node.id) {
|
640 | data = df._extract_data(node_json);
|
641 | var d = null;
|
642 | var node_direction = node_json.direction;
|
643 | if (!!node_direction) {
|
644 | d = node_direction == 'left' ? jm.direction.left : jm.direction.right;
|
645 | }
|
646 | var node = mind.add_node(parent_node, node_json.id, node_json.topic, data, d, node_json.expanded);
|
647 | node_array.splice(i, 1);
|
648 | extract_count++;
|
649 | var sub_extract_count = df._extract_subnode(mind, node, node_array);
|
650 | if (sub_extract_count > 0) {
|
651 |
|
652 | i = node_array.length;
|
653 | extract_count += sub_extract_count;
|
654 | }
|
655 | }
|
656 | }
|
657 | return extract_count;
|
658 | },
|
659 |
|
660 | _extract_data: function (node_json) {
|
661 | var data = {};
|
662 | for (var k in node_json) {
|
663 | if (k == 'id' || k == 'topic' || k == 'parentid' || k == 'isroot' || k == 'direction' || k == 'expanded') {
|
664 | continue;
|
665 | }
|
666 | data[k] = node_json[k];
|
667 | }
|
668 | return data;
|
669 | },
|
670 |
|
671 | _array: function (mind, node_array) {
|
672 | var df = jm.format.node_array;
|
673 | df._array_node(mind.root, node_array);
|
674 | },
|
675 |
|
676 | _array_node: function (node, node_array) {
|
677 | var df = jm.format.node_array;
|
678 | if (!(node instanceof jm.node)) { return; }
|
679 | var o = {
|
680 | id: node.id,
|
681 | topic: node.topic,
|
682 | expanded: node.expanded
|
683 | };
|
684 | if (!!node.parent) {
|
685 | o.parentid = node.parent.id;
|
686 | }
|
687 | if (node.isroot) {
|
688 | o.isroot = true;
|
689 | }
|
690 | if (!!node.parent && node.parent.isroot) {
|
691 | o.direction = node.direction == jm.direction.left ? 'left' : 'right';
|
692 | }
|
693 | if (node.data != null) {
|
694 | var node_data = node.data;
|
695 | for (var k in node_data) {
|
696 | o[k] = node_data[k];
|
697 | }
|
698 | }
|
699 | node_array.push(o);
|
700 | var ci = node.children.length;
|
701 | for (var i = 0; i < ci; i++) {
|
702 | df._array_node(node.children[i], node_array);
|
703 | }
|
704 | },
|
705 | },
|
706 |
|
707 | freemind: {
|
708 | example: {
|
709 | "meta": {
|
710 | "name": __name__,
|
711 | "author": __author__,
|
712 | "version": __version__
|
713 | },
|
714 | "format": "freemind",
|
715 | "data": "<map version=\"1.0.1\"><node ID=\"root\" TEXT=\"freemind Example\"/></map>"
|
716 | },
|
717 | get_mind: function (source) {
|
718 | var df = jm.format.freemind;
|
719 | var mind = new jm.mind();
|
720 | mind.name = source.meta.name;
|
721 | mind.author = source.meta.author;
|
722 | mind.version = source.meta.version;
|
723 | var xml = source.data;
|
724 | var xml_doc = df._parse_xml(xml);
|
725 | var xml_root = df._find_root(xml_doc);
|
726 | df._load_node(mind, null, xml_root);
|
727 | return mind;
|
728 | },
|
729 |
|
730 | get_data: function (mind) {
|
731 | var df = jm.format.freemind;
|
732 | var json = {};
|
733 | json.meta = {
|
734 | name: mind.name,
|
735 | author: mind.author,
|
736 | version: mind.version
|
737 | };
|
738 | json.format = 'freemind';
|
739 | var xmllines = [];
|
740 | xmllines.push('<map version=\"1.0.1\">');
|
741 | df._buildmap(mind.root, xmllines);
|
742 | xmllines.push('</map>');
|
743 | json.data = xmllines.join(' ');
|
744 | return json;
|
745 | },
|
746 |
|
747 | _parse_xml: function (xml) {
|
748 | var xml_doc = null;
|
749 | if (window.DOMParser) {
|
750 | var parser = new DOMParser();
|
751 | xml_doc = parser.parseFromString(xml, 'text/xml');
|
752 | } else {
|
753 | xml_doc = new ActiveXObject('Microsoft.XMLDOM');
|
754 | xml_doc.async = false;
|
755 | xml_doc.loadXML(xml);
|
756 | }
|
757 | return xml_doc;
|
758 | },
|
759 |
|
760 | _find_root: function (xml_doc) {
|
761 | var nodes = xml_doc.childNodes;
|
762 | var node = null;
|
763 | var root = null;
|
764 | var n = null;
|
765 | for (var i = 0; i < nodes.length; i++) {
|
766 | n = nodes[i];
|
767 | if (n.nodeType == 1 && n.tagName == 'map') {
|
768 | node = n;
|
769 | break;
|
770 | }
|
771 | }
|
772 | if (!!node) {
|
773 | var ns = node.childNodes;
|
774 | node = null;
|
775 | for (var i = 0; i < ns.length; i++) {
|
776 | n = ns[i];
|
777 | if (n.nodeType == 1 && n.tagName == 'node') {
|
778 | node = n;
|
779 | break;
|
780 | }
|
781 | }
|
782 | }
|
783 | return node;
|
784 | },
|
785 |
|
786 | _load_node: function (mind, parent_node, xml_node) {
|
787 | var df = jm.format.freemind;
|
788 | var node_id = xml_node.getAttribute('ID');
|
789 | var node_topic = xml_node.getAttribute('TEXT');
|
790 |
|
791 | if (node_topic == null) {
|
792 | var topic_children = xml_node.childNodes;
|
793 | var topic_child = null;
|
794 | for (var i = 0; i < topic_children.length; i++) {
|
795 | topic_child = topic_children[i];
|
796 |
|
797 | if (topic_child.nodeType == 1 && topic_child.tagName === 'richcontent') {
|
798 | node_topic = topic_child.textContent;
|
799 | break;
|
800 | }
|
801 | }
|
802 | }
|
803 | var node_data = df._load_attributes(xml_node);
|
804 | var node_expanded = ('expanded' in node_data) ? (node_data.expanded == 'true') : true;
|
805 | delete node_data.expanded;
|
806 |
|
807 | var node_position = xml_node.getAttribute('POSITION');
|
808 | var node_direction = null;
|
809 | if (!!node_position) {
|
810 | node_direction = node_position == 'left' ? jm.direction.left : jm.direction.right;
|
811 | }
|
812 |
|
813 | var node = null;
|
814 | if (!!parent_node) {
|
815 | node = mind.add_node(parent_node, node_id, node_topic, node_data, node_direction, node_expanded);
|
816 | } else {
|
817 | node = mind.set_root(node_id, node_topic, node_data);
|
818 | }
|
819 | var children = xml_node.childNodes;
|
820 | var child = null;
|
821 | for (var i = 0; i < children.length; i++) {
|
822 | child = children[i];
|
823 | if (child.nodeType == 1 && child.tagName == 'node') {
|
824 | df._load_node(mind, node, child);
|
825 | }
|
826 | }
|
827 | },
|
828 |
|
829 | _load_attributes: function (xml_node) {
|
830 | var children = xml_node.childNodes;
|
831 | var attr = null;
|
832 | var attr_data = {};
|
833 | for (var i = 0; i < children.length; i++) {
|
834 | attr = children[i];
|
835 | if (attr.nodeType == 1 && attr.tagName === 'attribute') {
|
836 | attr_data[attr.getAttribute('NAME')] = attr.getAttribute('VALUE');
|
837 | }
|
838 | }
|
839 | return attr_data;
|
840 | },
|
841 |
|
842 | _buildmap: function (node, xmllines) {
|
843 | var df = jm.format.freemind;
|
844 | var pos = null;
|
845 | if (!!node.parent && node.parent.isroot) {
|
846 | pos = node.direction === jm.direction.left ? 'left' : 'right';
|
847 | }
|
848 | xmllines.push('<node');
|
849 | xmllines.push('ID=\"' + node.id + '\"');
|
850 | if (!!pos) {
|
851 | xmllines.push('POSITION=\"' + pos + '\"');
|
852 | }
|
853 | xmllines.push('TEXT=\"' + node.topic + '\">');
|
854 |
|
855 |
|
856 | xmllines.push('<attribute NAME=\"expanded\" VALUE=\"' + node.expanded + '\"/>');
|
857 |
|
858 |
|
859 | var node_data = node.data;
|
860 | if (node_data != null) {
|
861 | for (var k in node_data) {
|
862 | xmllines.push('<attribute NAME=\"' + k + '\" VALUE=\"' + node_data[k] + '\"/>');
|
863 | }
|
864 | }
|
865 |
|
866 |
|
867 | var children = node.children;
|
868 | for (var i = 0; i < children.length; i++) {
|
869 | df._buildmap(children[i], xmllines);
|
870 | }
|
871 |
|
872 | xmllines.push('</node>');
|
873 | },
|
874 | },
|
875 | };
|
876 |
|
877 |
|
878 |
|
879 | jm.util = {
|
880 | is_node: function (node) {
|
881 | return !!node && node instanceof jm.node;
|
882 | },
|
883 | ajax: {
|
884 | request: function (url, param, method, callback, fail_callback) {
|
885 | var a = jm.util.ajax;
|
886 | var p = null;
|
887 | var tmp_param = [];
|
888 | for (var k in param) {
|
889 | tmp_param.push(encodeURIComponent(k) + '=' + encodeURIComponent(param[k]));
|
890 | }
|
891 | if (tmp_param.length > 0) {
|
892 | p = tmp_param.join('&');
|
893 | }
|
894 | var xhr = new XMLHttpRequest();
|
895 | if (!xhr) { return; }
|
896 | xhr.onreadystatechange = function () {
|
897 | if (xhr.readyState == 4) {
|
898 | if (xhr.status == 200 || xhr.status == 0) {
|
899 | if (typeof callback === 'function') {
|
900 | var data = jm.util.json.string2json(xhr.responseText);
|
901 | if (data != null) {
|
902 | callback(data);
|
903 | } else {
|
904 | callback(xhr.responseText);
|
905 | }
|
906 | }
|
907 | } else {
|
908 | if (typeof fail_callback === 'function') {
|
909 | fail_callback(xhr);
|
910 | } else {
|
911 | logger.error('xhr request failed.', xhr);
|
912 | }
|
913 | }
|
914 | }
|
915 | }
|
916 | method = method || 'GET';
|
917 | xhr.open(method, url, true);
|
918 | xhr.setRequestHeader('If-Modified-Since', '0');
|
919 | if (method == 'POST') {
|
920 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
|
921 | xhr.send(p);
|
922 | } else {
|
923 | xhr.send();
|
924 | }
|
925 | },
|
926 | get: function (url, callback) {
|
927 | return jm.util.ajax.request(url, {}, 'GET', callback);
|
928 | },
|
929 | post: function (url, param, callback) {
|
930 | return jm.util.ajax.request(url, param, 'POST', callback);
|
931 | }
|
932 | },
|
933 |
|
934 | dom: {
|
935 |
|
936 | add_event: function (t, e, h) {
|
937 | if (!!t.addEventListener) {
|
938 | t.addEventListener(e, h, false);
|
939 | } else {
|
940 | t.attachEvent('on' + e, h);
|
941 | }
|
942 | }
|
943 | },
|
944 |
|
945 | file: {
|
946 | read: function (file_data, fn_callback) {
|
947 | var reader = new FileReader();
|
948 | reader.onload = function () {
|
949 | if (typeof fn_callback === 'function') {
|
950 | fn_callback(this.result, file_data.name);
|
951 | }
|
952 | };
|
953 | reader.readAsText(file_data);
|
954 | },
|
955 |
|
956 | save: function (file_data, type, name) {
|
957 | var blob;
|
958 | if (typeof $w.Blob === 'function') {
|
959 | blob = new Blob([file_data], { type: type });
|
960 | } else {
|
961 | var BlobBuilder = $w.BlobBuilder || $w.MozBlobBuilder || $w.WebKitBlobBuilder || $w.MSBlobBuilder;
|
962 | var bb = new BlobBuilder();
|
963 | bb.append(file_data);
|
964 | blob = bb.getBlob(type);
|
965 | }
|
966 | if (navigator.msSaveBlob) {
|
967 | navigator.msSaveBlob(blob, name);
|
968 | } else {
|
969 | var URL = $w.URL || $w.webkitURL;
|
970 | var bloburl = URL.createObjectURL(blob);
|
971 | var anchor = $c('a');
|
972 | if ('download' in anchor) {
|
973 | anchor.style.visibility = 'hidden';
|
974 | anchor.href = bloburl;
|
975 | anchor.download = name;
|
976 | $d.body.appendChild(anchor);
|
977 | var evt = $d.createEvent('MouseEvents');
|
978 | evt.initEvent('click', true, true);
|
979 | anchor.dispatchEvent(evt);
|
980 | $d.body.removeChild(anchor);
|
981 | } else {
|
982 | location.href = bloburl;
|
983 | }
|
984 | }
|
985 | }
|
986 | },
|
987 |
|
988 | json: {
|
989 | json2string: function (json) {
|
990 | return JSON.stringify(json);
|
991 | },
|
992 | string2json: function (json_str) {
|
993 | return JSON.parse(json_str);
|
994 | },
|
995 | merge: function (b, a) {
|
996 | for (var o in a) {
|
997 | if (o in b) {
|
998 | if (typeof b[o] === 'object' &&
|
999 | Object.prototype.toString.call(b[o]).toLowerCase() == '[object object]' &&
|
1000 | !b[o].length) {
|
1001 | jm.util.json.merge(b[o], a[o]);
|
1002 | } else {
|
1003 | b[o] = a[o];
|
1004 | }
|
1005 | } else {
|
1006 | b[o] = a[o];
|
1007 | }
|
1008 | }
|
1009 | return b;
|
1010 | }
|
1011 | },
|
1012 |
|
1013 | uuid: {
|
1014 | newid: function () {
|
1015 | return (new Date().getTime().toString(16) + Math.random().toString(16).substring(2)).substring(2, 18);
|
1016 | }
|
1017 | },
|
1018 |
|
1019 | text: {
|
1020 | is_empty: function (s) {
|
1021 | if (!s) { return true; }
|
1022 | return s.replace(/\s*/, '').length == 0;
|
1023 | }
|
1024 | }
|
1025 | };
|
1026 |
|
1027 | jm.prototype = {
|
1028 | init: function () {
|
1029 | if (this.initialized) { return; }
|
1030 | this.initialized = true;
|
1031 |
|
1032 | var opts = this.options;
|
1033 |
|
1034 | var opts_layout = {
|
1035 | mode: opts.mode,
|
1036 | hspace: opts.layout.hspace,
|
1037 | vspace: opts.layout.vspace,
|
1038 | pspace: opts.layout.pspace,
|
1039 | cousin_space: opts.layout.cousin_space
|
1040 | }
|
1041 | var opts_view = {
|
1042 | container: opts.container,
|
1043 | support_html: opts.support_html,
|
1044 | engine: opts.view.engine,
|
1045 | hmargin: opts.view.hmargin,
|
1046 | vmargin: opts.view.vmargin,
|
1047 | line_width: opts.view.line_width,
|
1048 | line_color: opts.view.line_color,
|
1049 | draggable: opts.view.draggable,
|
1050 | hide_scrollbars_when_draggable: opts.view.hide_scrollbars_when_draggable,
|
1051 | node_overflow: opts.view.node_overflow
|
1052 | };
|
1053 |
|
1054 | this.data = new jm.data_provider(this);
|
1055 | this.layout = new jm.layout_provider(this, opts_layout);
|
1056 | this.view = new jm.view_provider(this, opts_view);
|
1057 | this.shortcut = new jm.shortcut_provider(this, opts.shortcut);
|
1058 |
|
1059 | this.data.init();
|
1060 | this.layout.init();
|
1061 | this.view.init();
|
1062 | this.shortcut.init();
|
1063 |
|
1064 | this._event_bind();
|
1065 |
|
1066 | jm.init_plugins(this);
|
1067 | },
|
1068 |
|
1069 | enable_edit: function () {
|
1070 | this.options.editable = true;
|
1071 | },
|
1072 |
|
1073 | disable_edit: function () {
|
1074 | this.options.editable = false;
|
1075 | },
|
1076 |
|
1077 |
|
1078 |
|
1079 | enable_event_handle: function (event_handle) {
|
1080 | this.options.default_event_handle['enable_' + event_handle + '_handle'] = true;
|
1081 | },
|
1082 |
|
1083 |
|
1084 |
|
1085 | disable_event_handle: function (event_handle) {
|
1086 | this.options.default_event_handle['enable_' + event_handle + '_handle'] = false;
|
1087 | },
|
1088 |
|
1089 | get_editable: function () {
|
1090 | return this.options.editable;
|
1091 | },
|
1092 |
|
1093 | set_theme: function (theme) {
|
1094 | var theme_old = this.options.theme;
|
1095 | this.options.theme = (!!theme) ? theme : null;
|
1096 | if (theme_old != this.options.theme) {
|
1097 | this.view.reset_theme();
|
1098 | this.view.reset_custom_style();
|
1099 | }
|
1100 | },
|
1101 | _event_bind: function () {
|
1102 | this.view.add_event(this, 'mousedown', this.mousedown_handle);
|
1103 | this.view.add_event(this, 'click', this.click_handle);
|
1104 | this.view.add_event(this, 'dblclick', this.dblclick_handle);
|
1105 | this.view.add_event(this, "mousewheel", this.mousewheel_handle)
|
1106 | },
|
1107 |
|
1108 | mousedown_handle: function (e) {
|
1109 | if (!this.options.default_event_handle['enable_mousedown_handle']) {
|
1110 | return;
|
1111 | }
|
1112 | var element = e.target || event.srcElement;
|
1113 | var nodeid = this.view.get_binded_nodeid(element);
|
1114 | if (!!nodeid) {
|
1115 | if (this.view.is_node(element)) {
|
1116 | this.select_node(nodeid);
|
1117 | }
|
1118 | } else {
|
1119 | this.select_clear();
|
1120 | }
|
1121 | },
|
1122 |
|
1123 | click_handle: function (e) {
|
1124 | if (!this.options.default_event_handle['enable_click_handle']) {
|
1125 | return;
|
1126 | }
|
1127 | var element = e.target || event.srcElement;
|
1128 | var is_expander = this.view.is_expander(element);
|
1129 | if (is_expander) {
|
1130 | var nodeid = this.view.get_binded_nodeid(element);
|
1131 | if (!!nodeid) {
|
1132 | this.toggle_node(nodeid);
|
1133 | }
|
1134 | }
|
1135 | },
|
1136 |
|
1137 | dblclick_handle: function (e) {
|
1138 | if (!this.options.default_event_handle['enable_dblclick_handle']) {
|
1139 | return;
|
1140 | }
|
1141 | if (this.get_editable()) {
|
1142 | var element = e.target || event.srcElement;
|
1143 | var is_node = this.view.is_node(element);
|
1144 | if (is_node) {
|
1145 | var nodeid = this.view.get_binded_nodeid(element);
|
1146 | if (!!nodeid) {
|
1147 | this.begin_edit(nodeid);
|
1148 | }
|
1149 | }
|
1150 | }
|
1151 | },
|
1152 |
|
1153 |
|
1154 | mousewheel_handle: function (event) {
|
1155 |
|
1156 | if (!this.options.default_event_handle["enable_mousewheel_handle"] || !window.event.ctrlKey) {
|
1157 | return
|
1158 | }
|
1159 |
|
1160 | event.preventDefault()
|
1161 |
|
1162 | if (event.deltaY < 0) {
|
1163 | this.view.zoomIn()
|
1164 | } else {
|
1165 | this.view.zoomOut()
|
1166 | }
|
1167 | },
|
1168 |
|
1169 | begin_edit: function (node) {
|
1170 | if (!jm.util.is_node(node)) {
|
1171 | var the_node = this.get_node(node);
|
1172 | if (!the_node) {
|
1173 | logger.error('the node[id=' + node + '] can not be found.');
|
1174 | return false;
|
1175 | } else {
|
1176 | return this.begin_edit(the_node);
|
1177 | }
|
1178 | }
|
1179 | if (this.get_editable()) {
|
1180 | this.view.edit_node_begin(node);
|
1181 | } else {
|
1182 | logger.error('fail, this mind map is not editable.');
|
1183 | return;
|
1184 | }
|
1185 | },
|
1186 |
|
1187 | end_edit: function () {
|
1188 | this.view.edit_node_end();
|
1189 | },
|
1190 |
|
1191 | toggle_node: function (node) {
|
1192 | if (!jm.util.is_node(node)) {
|
1193 | var the_node = this.get_node(node);
|
1194 | if (!the_node) {
|
1195 | logger.error('the node[id=' + node + '] can not be found.');
|
1196 | return;
|
1197 | } else {
|
1198 | return this.toggle_node(the_node);
|
1199 | }
|
1200 | }
|
1201 | if (node.isroot) { return; }
|
1202 | this.view.save_location(node);
|
1203 | this.layout.toggle_node(node);
|
1204 | this.view.relayout();
|
1205 | this.view.restore_location(node);
|
1206 | },
|
1207 |
|
1208 | expand_node: function (node) {
|
1209 | if (!jm.util.is_node(node)) {
|
1210 | var the_node = this.get_node(node);
|
1211 | if (!the_node) {
|
1212 | logger.error('the node[id=' + node + '] can not be found.');
|
1213 | return;
|
1214 | } else {
|
1215 | return this.expand_node(the_node);
|
1216 | }
|
1217 | }
|
1218 | if (node.isroot) { return; }
|
1219 | this.view.save_location(node);
|
1220 | this.layout.expand_node(node);
|
1221 | this.view.relayout();
|
1222 | this.view.restore_location(node);
|
1223 | },
|
1224 |
|
1225 | collapse_node: function (node) {
|
1226 | if (!jm.util.is_node(node)) {
|
1227 | var the_node = this.get_node(node);
|
1228 | if (!the_node) {
|
1229 | logger.error('the node[id=' + node + '] can not be found.');
|
1230 | return;
|
1231 | } else {
|
1232 | return this.collapse_node(the_node);
|
1233 | }
|
1234 | }
|
1235 | if (node.isroot) { return; }
|
1236 | this.view.save_location(node);
|
1237 | this.layout.collapse_node(node);
|
1238 | this.view.relayout();
|
1239 | this.view.restore_location(node);
|
1240 | },
|
1241 |
|
1242 | expand_all: function () {
|
1243 | this.layout.expand_all();
|
1244 | this.view.relayout();
|
1245 | },
|
1246 |
|
1247 | collapse_all: function () {
|
1248 | this.layout.collapse_all();
|
1249 | this.view.relayout();
|
1250 | },
|
1251 |
|
1252 | expand_to_depth: function (depth) {
|
1253 | this.layout.expand_to_depth(depth);
|
1254 | this.view.relayout();
|
1255 | },
|
1256 |
|
1257 | _reset: function () {
|
1258 | this.view.reset();
|
1259 | this.layout.reset();
|
1260 | this.data.reset();
|
1261 | },
|
1262 |
|
1263 | _show: function (mind) {
|
1264 | var m = mind || jm.format.node_array.example;
|
1265 |
|
1266 | this.mind = this.data.load(m);
|
1267 | if (!this.mind) {
|
1268 | logger.error('data.load error');
|
1269 | return;
|
1270 | } else {
|
1271 | logger.debug('data.load ok');
|
1272 | }
|
1273 |
|
1274 | this.view.load();
|
1275 | logger.debug('view.load ok');
|
1276 |
|
1277 | this.layout.layout();
|
1278 | logger.debug('layout.layout ok');
|
1279 |
|
1280 | this.view.show(true);
|
1281 | logger.debug('view.show ok');
|
1282 |
|
1283 | this.invoke_event_handle(jm.event_type.show, { data: [mind] });
|
1284 | },
|
1285 |
|
1286 | show: function (mind) {
|
1287 | this._reset();
|
1288 | this._show(mind);
|
1289 | },
|
1290 |
|
1291 | get_meta: function () {
|
1292 | return {
|
1293 | name: this.mind.name,
|
1294 | author: this.mind.author,
|
1295 | version: this.mind.version
|
1296 | };
|
1297 | },
|
1298 |
|
1299 | get_data: function (data_format) {
|
1300 | var df = data_format || 'node_tree';
|
1301 | return this.data.get_data(df);
|
1302 | },
|
1303 |
|
1304 | get_root: function () {
|
1305 | return this.mind.root;
|
1306 | },
|
1307 |
|
1308 | get_node: function (node) {
|
1309 | if (jm.util.is_node(node)) {
|
1310 | return node;
|
1311 | }
|
1312 | return this.mind.get_node(node);
|
1313 | },
|
1314 |
|
1315 | add_node: function (parent_node, nodeid, topic, data, direction) {
|
1316 | if (this.get_editable()) {
|
1317 | var the_parent_node = this.get_node(parent_node);
|
1318 | var dir = jm.direction.of(direction)
|
1319 | if (dir === undefined) {
|
1320 | dir = this.layout.calculate_next_child_direction(the_parent_node);
|
1321 | }
|
1322 | var node = this.mind.add_node(the_parent_node, nodeid, topic, data, dir);
|
1323 | if (!!node) {
|
1324 | this.view.add_node(node);
|
1325 | this.layout.layout();
|
1326 | this.view.show(false);
|
1327 | this.view.reset_node_custom_style(node);
|
1328 | this.expand_node(the_parent_node);
|
1329 | this.invoke_event_handle(jm.event_type.edit, { evt: 'add_node', data: [the_parent_node.id, nodeid, topic, data, dir], node: nodeid });
|
1330 | }
|
1331 | return node;
|
1332 | } else {
|
1333 | logger.error('fail, this mind map is not editable');
|
1334 | return null;
|
1335 | }
|
1336 | },
|
1337 |
|
1338 | insert_node_before: function (node_before, nodeid, topic, data, direction) {
|
1339 | if (this.get_editable()) {
|
1340 | var the_node_before = this.get_node(node_before);
|
1341 | var dir = jm.direction.of(direction)
|
1342 | if (dir === undefined) {
|
1343 | dir = this.layout.calculate_next_child_direction(the_node_before.parent);
|
1344 | }
|
1345 | var node = this.mind.insert_node_before(the_node_before, nodeid, topic, data, dir);
|
1346 | if (!!node) {
|
1347 | this.view.add_node(node);
|
1348 | this.layout.layout();
|
1349 | this.view.show(false);
|
1350 | this.invoke_event_handle(jm.event_type.edit, { evt: 'insert_node_before', data: [the_node_before.id, nodeid, topic, data, dir], node: nodeid });
|
1351 | }
|
1352 | return node;
|
1353 | } else {
|
1354 | logger.error('fail, this mind map is not editable');
|
1355 | return null;
|
1356 | }
|
1357 | },
|
1358 |
|
1359 | insert_node_after: function (node_after, nodeid, topic, data, direction) {
|
1360 | if (this.get_editable()) {
|
1361 | var the_node_after = this.get_node(node_after);
|
1362 | var dir = jm.direction.of(direction)
|
1363 | if (dir === undefined) {
|
1364 | dir = this.layout.calculate_next_child_direction(the_node_after.parent);
|
1365 | }
|
1366 | var node = this.mind.insert_node_after(the_node_after, nodeid, topic, data, dir);
|
1367 | if (!!node) {
|
1368 | this.view.add_node(node);
|
1369 | this.layout.layout();
|
1370 | this.view.show(false);
|
1371 | this.invoke_event_handle(jm.event_type.edit, { evt: 'insert_node_after', data: [the_node_after.id, nodeid, topic, data, dir], node: nodeid });
|
1372 | }
|
1373 | return node;
|
1374 | } else {
|
1375 | logger.error('fail, this mind map is not editable');
|
1376 | return null;
|
1377 | }
|
1378 | },
|
1379 |
|
1380 | remove_node: function (node) {
|
1381 | if (!jm.util.is_node(node)) {
|
1382 | var the_node = this.get_node(node);
|
1383 | if (!the_node) {
|
1384 | logger.error('the node[id=' + node + '] can not be found.');
|
1385 | return false;
|
1386 | } else {
|
1387 | return this.remove_node(the_node);
|
1388 | }
|
1389 | }
|
1390 | if (this.get_editable()) {
|
1391 | if (node.isroot) {
|
1392 | logger.error('fail, can not remove root node');
|
1393 | return false;
|
1394 | }
|
1395 | var nodeid = node.id;
|
1396 | var parentid = node.parent.id;
|
1397 | var parent_node = this.get_node(parentid);
|
1398 | this.view.save_location(parent_node);
|
1399 | this.view.remove_node(node);
|
1400 | this.mind.remove_node(node);
|
1401 | this.layout.layout();
|
1402 | this.view.show(false);
|
1403 | this.view.restore_location(parent_node);
|
1404 | this.invoke_event_handle(jm.event_type.edit, { evt: 'remove_node', data: [nodeid], node: parentid });
|
1405 | return true;
|
1406 | } else {
|
1407 | logger.error('fail, this mind map is not editable');
|
1408 | return false;
|
1409 | }
|
1410 | },
|
1411 |
|
1412 | update_node: function (nodeid, topic) {
|
1413 | if (this.get_editable()) {
|
1414 | if (jm.util.text.is_empty(topic)) {
|
1415 | logger.warn('fail, topic can not be empty');
|
1416 | return;
|
1417 | }
|
1418 | var node = this.get_node(nodeid);
|
1419 | if (!!node) {
|
1420 | if (node.topic === topic) {
|
1421 | logger.info('nothing changed');
|
1422 | this.view.update_node(node);
|
1423 | return;
|
1424 | }
|
1425 | node.topic = topic;
|
1426 | this.view.update_node(node);
|
1427 | this.layout.layout();
|
1428 | this.view.show(false);
|
1429 | this.invoke_event_handle(jm.event_type.edit, { evt: 'update_node', data: [nodeid, topic], node: nodeid });
|
1430 | }
|
1431 | } else {
|
1432 | logger.error('fail, this mind map is not editable');
|
1433 | return;
|
1434 | }
|
1435 | },
|
1436 |
|
1437 | move_node: function (nodeid, beforeid, parentid, direction) {
|
1438 | if (this.get_editable()) {
|
1439 | var node = this.get_node(nodeid);
|
1440 | var updated_node = this.mind.move_node(node, beforeid, parentid, direction);
|
1441 | if (!!updated_node) {
|
1442 | this.view.update_node(updated_node);
|
1443 | this.layout.layout();
|
1444 | this.view.show(false);
|
1445 | this.invoke_event_handle(jm.event_type.edit, { evt: 'move_node', data: [nodeid, beforeid, parentid, direction], node: nodeid });
|
1446 | }
|
1447 | } else {
|
1448 | logger.error('fail, this mind map is not editable');
|
1449 | return;
|
1450 | }
|
1451 | },
|
1452 |
|
1453 | select_node: function (node) {
|
1454 | if (!jm.util.is_node(node)) {
|
1455 | var the_node = this.get_node(node);
|
1456 | if (!the_node) {
|
1457 | logger.error('the node[id=' + node + '] can not be found.');
|
1458 | return;
|
1459 | } else {
|
1460 | return this.select_node(the_node);
|
1461 | }
|
1462 | }
|
1463 | if (!this.layout.is_visible(node)) {
|
1464 | return;
|
1465 | }
|
1466 | this.mind.selected = node;
|
1467 | this.view.select_node(node);
|
1468 | this.invoke_event_handle(jm.event_type.select, { evt: 'select_node', data: [], node: node.id });
|
1469 | },
|
1470 |
|
1471 | get_selected_node: function () {
|
1472 | if (!!this.mind) {
|
1473 | return this.mind.selected;
|
1474 | } else {
|
1475 | return null;
|
1476 | }
|
1477 | },
|
1478 |
|
1479 | select_clear: function () {
|
1480 | if (!!this.mind) {
|
1481 | this.mind.selected = null;
|
1482 | this.view.select_clear();
|
1483 | }
|
1484 | },
|
1485 |
|
1486 | is_node_visible: function (node) {
|
1487 | return this.layout.is_visible(node);
|
1488 | },
|
1489 |
|
1490 | find_node_before: function (node) {
|
1491 | if (!jm.util.is_node(node)) {
|
1492 | var the_node = this.get_node(node);
|
1493 | if (!the_node) {
|
1494 | logger.error('the node[id=' + node + '] can not be found.');
|
1495 | return;
|
1496 | } else {
|
1497 | return this.find_node_before(the_node);
|
1498 | }
|
1499 | }
|
1500 | if (node.isroot) { return null; }
|
1501 | var n = null;
|
1502 | if (node.parent.isroot) {
|
1503 | var c = node.parent.children;
|
1504 | var prev = null;
|
1505 | var ni = null;
|
1506 | for (var i = 0; i < c.length; i++) {
|
1507 | ni = c[i];
|
1508 | if (node.direction === ni.direction) {
|
1509 | if (node.id === ni.id) {
|
1510 | n = prev;
|
1511 | }
|
1512 | prev = ni;
|
1513 | }
|
1514 | }
|
1515 | } else {
|
1516 | n = this.mind.get_node_before(node);
|
1517 | }
|
1518 | return n;
|
1519 | },
|
1520 |
|
1521 | find_node_after: function (node) {
|
1522 | if (!jm.util.is_node(node)) {
|
1523 | var the_node = this.get_node(node);
|
1524 | if (!the_node) {
|
1525 | logger.error('the node[id=' + node + '] can not be found.');
|
1526 | return;
|
1527 | } else {
|
1528 | return this.find_node_after(the_node);
|
1529 | }
|
1530 | }
|
1531 | if (node.isroot) { return null; }
|
1532 | var n = null;
|
1533 | if (node.parent.isroot) {
|
1534 | var c = node.parent.children;
|
1535 | var getthis = false;
|
1536 | var ni = null;
|
1537 | for (var i = 0; i < c.length; i++) {
|
1538 | ni = c[i];
|
1539 | if (node.direction === ni.direction) {
|
1540 | if (getthis) {
|
1541 | n = ni;
|
1542 | break;
|
1543 | }
|
1544 | if (node.id === ni.id) {
|
1545 | getthis = true;
|
1546 | }
|
1547 | }
|
1548 | }
|
1549 | } else {
|
1550 | n = this.mind.get_node_after(node);
|
1551 | }
|
1552 | return n;
|
1553 | },
|
1554 |
|
1555 | set_node_color: function (nodeid, bgcolor, fgcolor) {
|
1556 | if (this.get_editable()) {
|
1557 | var node = this.mind.get_node(nodeid);
|
1558 | if (!!node) {
|
1559 | if (!!bgcolor) {
|
1560 | node.data['background-color'] = bgcolor;
|
1561 | }
|
1562 | if (!!fgcolor) {
|
1563 | node.data['foreground-color'] = fgcolor;
|
1564 | }
|
1565 | this.view.reset_node_custom_style(node);
|
1566 | }
|
1567 | } else {
|
1568 | logger.error('fail, this mind map is not editable');
|
1569 | return null;
|
1570 | }
|
1571 | },
|
1572 |
|
1573 | set_node_font_style: function (nodeid, size, weight, style) {
|
1574 | if (this.get_editable()) {
|
1575 | var node = this.mind.get_node(nodeid);
|
1576 | if (!!node) {
|
1577 | if (!!size) {
|
1578 | node.data['font-size'] = size;
|
1579 | }
|
1580 | if (!!weight) {
|
1581 | node.data['font-weight'] = weight;
|
1582 | }
|
1583 | if (!!style) {
|
1584 | node.data['font-style'] = style;
|
1585 | }
|
1586 | this.view.reset_node_custom_style(node);
|
1587 | this.view.update_node(node);
|
1588 | this.layout.layout();
|
1589 | this.view.show(false);
|
1590 | }
|
1591 | } else {
|
1592 | logger.error('fail, this mind map is not editable');
|
1593 | return null;
|
1594 | }
|
1595 | },
|
1596 |
|
1597 | set_node_background_image: function (nodeid, image, width, height, rotation) {
|
1598 | if (this.get_editable()) {
|
1599 | var node = this.mind.get_node(nodeid);
|
1600 | if (!!node) {
|
1601 | if (!!image) {
|
1602 | node.data['background-image'] = image;
|
1603 | }
|
1604 | if (!!width) {
|
1605 | node.data['width'] = width;
|
1606 | }
|
1607 | if (!!height) {
|
1608 | node.data['height'] = height;
|
1609 | }
|
1610 | if (!!rotation) {
|
1611 | node.data['background-rotation'] = rotation;
|
1612 | }
|
1613 | this.view.reset_node_custom_style(node);
|
1614 | this.view.update_node(node);
|
1615 | this.layout.layout();
|
1616 | this.view.show(false);
|
1617 | }
|
1618 | } else {
|
1619 | logger.error('fail, this mind map is not editable');
|
1620 | return null;
|
1621 | }
|
1622 | },
|
1623 |
|
1624 | set_node_background_rotation: function (nodeid, rotation) {
|
1625 | if (this.get_editable()) {
|
1626 | var node = this.mind.get_node(nodeid);
|
1627 | if (!!node) {
|
1628 | if (!node.data['background-image']) {
|
1629 | logger.error('fail, only can change rotation angle of node with background image');
|
1630 | return null;
|
1631 | }
|
1632 | node.data['background-rotation'] = rotation;
|
1633 | this.view.reset_node_custom_style(node);
|
1634 | this.view.update_node(node);
|
1635 | this.layout.layout();
|
1636 | this.view.show(false);
|
1637 | }
|
1638 | } else {
|
1639 | logger.error('fail, this mind map is not editable');
|
1640 | return null;
|
1641 | }
|
1642 | },
|
1643 |
|
1644 | resize: function () {
|
1645 | this.view.resize();
|
1646 | },
|
1647 |
|
1648 |
|
1649 | add_event_listener: function (callback) {
|
1650 | if (typeof callback === 'function') {
|
1651 | this.event_handles.push(callback);
|
1652 | }
|
1653 | },
|
1654 |
|
1655 | clear_event_listener: function () {
|
1656 | this.event_handles = [];
|
1657 | },
|
1658 |
|
1659 | invoke_event_handle: function (type, data) {
|
1660 | var j = this;
|
1661 | $w.setTimeout(function () {
|
1662 | j._invoke_event_handle(type, data);
|
1663 | }, 0);
|
1664 | },
|
1665 |
|
1666 | _invoke_event_handle: function (type, data) {
|
1667 | var l = this.event_handles.length;
|
1668 | for (var i = 0; i < l; i++) {
|
1669 | this.event_handles[i](type, data);
|
1670 | }
|
1671 | },
|
1672 |
|
1673 | };
|
1674 |
|
1675 |
|
1676 |
|
1677 | jm.data_provider = function (jm) {
|
1678 | this.jm = jm;
|
1679 | };
|
1680 |
|
1681 | jm.data_provider.prototype = {
|
1682 | init: function () {
|
1683 | logger.debug('data.init');
|
1684 | },
|
1685 |
|
1686 | reset: function () {
|
1687 | logger.debug('data.reset');
|
1688 | },
|
1689 |
|
1690 | load: function (mind_data) {
|
1691 | var df = null;
|
1692 | var mind = null;
|
1693 | if (typeof mind_data === 'object') {
|
1694 | if (!!mind_data.format) {
|
1695 | df = mind_data.format;
|
1696 | } else {
|
1697 | df = 'node_tree';
|
1698 | }
|
1699 | } else {
|
1700 | df = 'freemind';
|
1701 | }
|
1702 |
|
1703 | if (df == 'node_array') {
|
1704 | mind = jm.format.node_array.get_mind(mind_data);
|
1705 | } else if (df == 'node_tree') {
|
1706 | mind = jm.format.node_tree.get_mind(mind_data);
|
1707 | } else if (df == 'freemind') {
|
1708 | mind = jm.format.freemind.get_mind(mind_data);
|
1709 | } else {
|
1710 | logger.warn('unsupported format');
|
1711 | }
|
1712 | return mind;
|
1713 | },
|
1714 |
|
1715 | get_data: function (data_format) {
|
1716 | var data = null;
|
1717 | if (data_format == 'node_array') {
|
1718 | data = jm.format.node_array.get_data(this.jm.mind);
|
1719 | } else if (data_format == 'node_tree') {
|
1720 | data = jm.format.node_tree.get_data(this.jm.mind);
|
1721 | } else if (data_format == 'freemind') {
|
1722 | data = jm.format.freemind.get_data(this.jm.mind);
|
1723 | } else {
|
1724 | logger.error('unsupported ' + data_format + ' format');
|
1725 | }
|
1726 | return data;
|
1727 | },
|
1728 | };
|
1729 |
|
1730 |
|
1731 |
|
1732 | jm.layout_provider = function (jm, options) {
|
1733 | this.opts = options;
|
1734 | this.jm = jm;
|
1735 | this.isside = (this.opts.mode == 'side');
|
1736 | this.bounds = null;
|
1737 |
|
1738 | this.cache_valid = false;
|
1739 | };
|
1740 |
|
1741 | jm.layout_provider.prototype = {
|
1742 | init: function () {
|
1743 | logger.debug('layout.init');
|
1744 | },
|
1745 |
|
1746 | reset: function () {
|
1747 | logger.debug('layout.reset');
|
1748 | this.bounds = { n: 0, s: 0, w: 0, e: 0 };
|
1749 | },
|
1750 |
|
1751 | calculate_next_child_direction: function (node) {
|
1752 | if (this.isside) {
|
1753 | return jm.direction.right;
|
1754 | }
|
1755 | var children = node.children || [];
|
1756 | var children_len = children.length;
|
1757 | var r = 0;
|
1758 | for (var i = 0; i < children_len; i++) { if (children[i].direction === jm.direction.left) { r--; } else { r++; } }
|
1759 | return (children_len > 1 && r > 0) ? jm.direction.left : jm.direction.right;
|
1760 | },
|
1761 |
|
1762 | layout: function () {
|
1763 | logger.debug('layout.layout');
|
1764 | this.layout_direction();
|
1765 | this.layout_offset();
|
1766 | },
|
1767 |
|
1768 | layout_direction: function () {
|
1769 | this._layout_direction_root();
|
1770 | },
|
1771 |
|
1772 | _layout_direction_root: function () {
|
1773 | var node = this.jm.mind.root;
|
1774 |
|
1775 | var layout_data = null;
|
1776 | if ('layout' in node._data) {
|
1777 | layout_data = node._data.layout;
|
1778 | } else {
|
1779 | layout_data = {};
|
1780 | node._data.layout = layout_data;
|
1781 | }
|
1782 | var children = node.children;
|
1783 | var children_count = children.length;
|
1784 | layout_data.direction = jm.direction.center;
|
1785 | layout_data.side_index = 0;
|
1786 | if (this.isside) {
|
1787 | var i = children_count;
|
1788 | while (i--) {
|
1789 | this._layout_direction_side(children[i], jm.direction.right, i);
|
1790 | }
|
1791 | } else {
|
1792 | var i = children_count;
|
1793 | var subnode = null;
|
1794 | while (i--) {
|
1795 | subnode = children[i];
|
1796 | if (subnode.direction == jm.direction.left) {
|
1797 | this._layout_direction_side(subnode, jm.direction.left, i);
|
1798 | } else {
|
1799 | this._layout_direction_side(subnode, jm.direction.right, i);
|
1800 | }
|
1801 | }
|
1802 | |
1803 |
|
1804 |
|
1805 |
|
1806 |
|
1807 |
|
1808 |
|
1809 |
|
1810 |
|
1811 |
|
1812 |
|
1813 | }
|
1814 | },
|
1815 |
|
1816 | _layout_direction_side: function (node, direction, side_index) {
|
1817 | var layout_data = null;
|
1818 | if ('layout' in node._data) {
|
1819 | layout_data = node._data.layout;
|
1820 | } else {
|
1821 | layout_data = {};
|
1822 | node._data.layout = layout_data;
|
1823 | }
|
1824 | var children = node.children;
|
1825 | var children_count = children.length;
|
1826 |
|
1827 | layout_data.direction = direction;
|
1828 | layout_data.side_index = side_index;
|
1829 | var i = children_count;
|
1830 | while (i--) {
|
1831 | this._layout_direction_side(children[i], direction, i);
|
1832 | }
|
1833 | },
|
1834 |
|
1835 | layout_offset: function () {
|
1836 | var node = this.jm.mind.root;
|
1837 | var layout_data = node._data.layout;
|
1838 | layout_data.offset_x = 0;
|
1839 | layout_data.offset_y = 0;
|
1840 | layout_data.outer_height = 0;
|
1841 | var children = node.children;
|
1842 | var i = children.length;
|
1843 | var left_nodes = [];
|
1844 | var right_nodes = [];
|
1845 | var subnode = null;
|
1846 | while (i--) {
|
1847 | subnode = children[i];
|
1848 | if (subnode._data.layout.direction == jm.direction.right) {
|
1849 | right_nodes.unshift(subnode);
|
1850 | } else {
|
1851 | left_nodes.unshift(subnode);
|
1852 | }
|
1853 | }
|
1854 | layout_data.left_nodes = left_nodes;
|
1855 | layout_data.right_nodes = right_nodes;
|
1856 | layout_data.outer_height_left = this._layout_offset_subnodes(left_nodes);
|
1857 | layout_data.outer_height_right = this._layout_offset_subnodes(right_nodes);
|
1858 | this.bounds.e = node._data.view.width / 2;
|
1859 | this.bounds.w = 0 - this.bounds.e;
|
1860 |
|
1861 | this.bounds.n = 0;
|
1862 | this.bounds.s = Math.max(layout_data.outer_height_left, layout_data.outer_height_right);
|
1863 | },
|
1864 |
|
1865 |
|
1866 | _layout_offset_subnodes: function (nodes) {
|
1867 | var total_height = 0;
|
1868 | var nodes_count = nodes.length;
|
1869 | var i = nodes_count;
|
1870 | var node = null;
|
1871 | var node_outer_height = 0;
|
1872 | var layout_data = null;
|
1873 | var base_y = 0;
|
1874 | var pd = null;
|
1875 | while (i--) {
|
1876 | node = nodes[i];
|
1877 | layout_data = node._data.layout;
|
1878 | if (pd == null) {
|
1879 | pd = node.parent._data;
|
1880 | }
|
1881 |
|
1882 | node_outer_height = this._layout_offset_subnodes(node.children);
|
1883 | if (!node.expanded) {
|
1884 | node_outer_height = 0;
|
1885 | this.set_visible(node.children, false);
|
1886 | }
|
1887 | node_outer_height = Math.max(node._data.view.height, node_outer_height);
|
1888 | if (node.children.length > 1) {
|
1889 | node_outer_height += this.opts.cousin_space;
|
1890 | }
|
1891 |
|
1892 | layout_data.outer_height = node_outer_height;
|
1893 | layout_data.offset_y = base_y - node_outer_height / 2;
|
1894 | layout_data.offset_x = this.opts.hspace * layout_data.direction + pd.view.width * (pd.layout.direction + layout_data.direction) / 2;
|
1895 | if (!node.parent.isroot) {
|
1896 | layout_data.offset_x += this.opts.pspace * layout_data.direction;
|
1897 | }
|
1898 |
|
1899 | base_y = base_y - node_outer_height - this.opts.vspace;
|
1900 | total_height += node_outer_height;
|
1901 | }
|
1902 | if (nodes_count > 1) {
|
1903 | total_height += this.opts.vspace * (nodes_count - 1);
|
1904 | }
|
1905 | i = nodes_count;
|
1906 | var middle_height = total_height / 2;
|
1907 | while (i--) {
|
1908 | node = nodes[i];
|
1909 | node._data.layout.offset_y += middle_height;
|
1910 | }
|
1911 | return total_height;
|
1912 | },
|
1913 |
|
1914 |
|
1915 | _layout_offset_subnodes_height: function (nodes) {
|
1916 | var total_height = 0;
|
1917 | var nodes_count = nodes.length;
|
1918 | var i = nodes_count;
|
1919 | var node = null;
|
1920 | var node_outer_height = 0;
|
1921 | var layout_data = null;
|
1922 | var base_y = 0;
|
1923 | var pd = null;
|
1924 | while (i--) {
|
1925 | node = nodes[i];
|
1926 | layout_data = node._data.layout;
|
1927 | if (pd == null) {
|
1928 | pd = node.parent._data;
|
1929 | }
|
1930 |
|
1931 | node_outer_height = this._layout_offset_subnodes_height(node.children);
|
1932 | if (!node.expanded) {
|
1933 | node_outer_height = 0;
|
1934 | }
|
1935 | node_outer_height = Math.max(node._data.view.height, node_outer_height);
|
1936 | if (node.children.length > 1) {
|
1937 | node_outer_height += this.opts.cousin_space;
|
1938 | }
|
1939 |
|
1940 | layout_data.outer_height = node_outer_height;
|
1941 | layout_data.offset_y = base_y - node_outer_height / 2;
|
1942 | base_y = base_y - node_outer_height - this.opts.vspace;
|
1943 | total_height += node_outer_height;
|
1944 | }
|
1945 | if (nodes_count > 1) {
|
1946 | total_height += this.opts.vspace * (nodes_count - 1);
|
1947 | }
|
1948 | i = nodes_count;
|
1949 | var middle_height = total_height / 2;
|
1950 | while (i--) {
|
1951 | node = nodes[i];
|
1952 | node._data.layout.offset_y += middle_height;
|
1953 |
|
1954 |
|
1955 | }
|
1956 | return total_height;
|
1957 | },
|
1958 |
|
1959 | get_node_offset: function (node) {
|
1960 | var layout_data = node._data.layout;
|
1961 | var offset_cache = null;
|
1962 | if (('_offset_' in layout_data) && this.cache_valid) {
|
1963 | offset_cache = layout_data._offset_;
|
1964 | } else {
|
1965 | offset_cache = { x: -1, y: -1 };
|
1966 | layout_data._offset_ = offset_cache;
|
1967 | }
|
1968 | if (offset_cache.x == -1 || offset_cache.y == -1) {
|
1969 | var x = layout_data.offset_x;
|
1970 | var y = layout_data.offset_y;
|
1971 | if (!node.isroot) {
|
1972 | var offset_p = this.get_node_offset(node.parent);
|
1973 | x += offset_p.x;
|
1974 | y += offset_p.y;
|
1975 | }
|
1976 | offset_cache.x = x;
|
1977 | offset_cache.y = y;
|
1978 | }
|
1979 | return offset_cache;
|
1980 | },
|
1981 |
|
1982 | get_node_point: function (node) {
|
1983 | var view_data = node._data.view;
|
1984 | var offset_p = this.get_node_offset(node);
|
1985 |
|
1986 | var p = {};
|
1987 | p.x = offset_p.x + view_data.width * (node._data.layout.direction - 1) / 2;
|
1988 | p.y = offset_p.y - view_data.height / 2;
|
1989 |
|
1990 | return p;
|
1991 | },
|
1992 |
|
1993 | get_node_point_in: function (node) {
|
1994 | var p = this.get_node_offset(node);
|
1995 | return p;
|
1996 | },
|
1997 |
|
1998 | get_node_point_out: function (node) {
|
1999 | var layout_data = node._data.layout;
|
2000 | var pout_cache = null;
|
2001 | if (('_pout_' in layout_data) && this.cache_valid) {
|
2002 | pout_cache = layout_data._pout_;
|
2003 | } else {
|
2004 | pout_cache = { x: -1, y: -1 };
|
2005 | layout_data._pout_ = pout_cache;
|
2006 | }
|
2007 | if (pout_cache.x == -1 || pout_cache.y == -1) {
|
2008 | if (node.isroot) {
|
2009 | pout_cache.x = 0;
|
2010 | pout_cache.y = 0;
|
2011 | } else {
|
2012 | var view_data = node._data.view;
|
2013 | var offset_p = this.get_node_offset(node);
|
2014 | pout_cache.x = offset_p.x + (view_data.width + this.opts.pspace) * node._data.layout.direction;
|
2015 | pout_cache.y = offset_p.y;
|
2016 |
|
2017 |
|
2018 | }
|
2019 | }
|
2020 | return pout_cache;
|
2021 | },
|
2022 |
|
2023 | get_expander_point: function (node) {
|
2024 | var p = this.get_node_point_out(node);
|
2025 | var ex_p = {};
|
2026 | if (node._data.layout.direction == jm.direction.right) {
|
2027 | ex_p.x = p.x - this.opts.pspace;
|
2028 | } else {
|
2029 | ex_p.x = p.x;
|
2030 | }
|
2031 | ex_p.y = p.y - Math.ceil(this.opts.pspace / 2);
|
2032 | return ex_p;
|
2033 | },
|
2034 |
|
2035 | get_min_size: function () {
|
2036 | var nodes = this.jm.mind.nodes;
|
2037 | var node = null;
|
2038 | var pout = null;
|
2039 | for (var nodeid in nodes) {
|
2040 | node = nodes[nodeid];
|
2041 | pout = this.get_node_point_out(node);
|
2042 | if (pout.x > this.bounds.e) { this.bounds.e = pout.x; }
|
2043 | if (pout.x < this.bounds.w) { this.bounds.w = pout.x; }
|
2044 | }
|
2045 | return {
|
2046 | w: this.bounds.e - this.bounds.w,
|
2047 | h: this.bounds.s - this.bounds.n
|
2048 | }
|
2049 | },
|
2050 |
|
2051 | toggle_node: function (node) {
|
2052 | if (node.isroot) {
|
2053 | return;
|
2054 | }
|
2055 | if (node.expanded) {
|
2056 | this.collapse_node(node);
|
2057 | } else {
|
2058 | this.expand_node(node);
|
2059 | }
|
2060 | },
|
2061 |
|
2062 | expand_node: function (node) {
|
2063 | node.expanded = true;
|
2064 | this.part_layout(node);
|
2065 | this.set_visible(node.children, true);
|
2066 | this.jm.invoke_event_handle(jm.event_type.show, { evt: 'expand_node', data: [], node: node.id });
|
2067 | },
|
2068 |
|
2069 | collapse_node: function (node) {
|
2070 | node.expanded = false;
|
2071 | this.part_layout(node);
|
2072 | this.set_visible(node.children, false);
|
2073 | this.jm.invoke_event_handle(jm.event_type.show, { evt: 'collapse_node', data: [], node: node.id });
|
2074 | },
|
2075 |
|
2076 | expand_all: function () {
|
2077 | var nodes = this.jm.mind.nodes;
|
2078 | var c = 0;
|
2079 | var node;
|
2080 | for (var nodeid in nodes) {
|
2081 | node = nodes[nodeid];
|
2082 | if (!node.expanded) {
|
2083 | node.expanded = true;
|
2084 | c++;
|
2085 | }
|
2086 | }
|
2087 | if (c > 0) {
|
2088 | var root = this.jm.mind.root;
|
2089 | this.part_layout(root);
|
2090 | this.set_visible(root.children, true);
|
2091 | }
|
2092 | },
|
2093 |
|
2094 | collapse_all: function () {
|
2095 | var nodes = this.jm.mind.nodes;
|
2096 | var c = 0;
|
2097 | var node;
|
2098 | for (var nodeid in nodes) {
|
2099 | node = nodes[nodeid];
|
2100 | if (node.expanded && !node.isroot) {
|
2101 | node.expanded = false;
|
2102 | c++;
|
2103 | }
|
2104 | }
|
2105 | if (c > 0) {
|
2106 | var root = this.jm.mind.root;
|
2107 | this.part_layout(root);
|
2108 | this.set_visible(root.children, true);
|
2109 | }
|
2110 | },
|
2111 |
|
2112 | expand_to_depth: function (target_depth, curr_nodes, curr_depth) {
|
2113 | if (target_depth < 1) { return; }
|
2114 | var nodes = curr_nodes || this.jm.mind.root.children;
|
2115 | var depth = curr_depth || 1;
|
2116 | var i = nodes.length;
|
2117 | var node = null;
|
2118 | while (i--) {
|
2119 | node = nodes[i];
|
2120 | if (depth < target_depth) {
|
2121 | if (!node.expanded) {
|
2122 | this.expand_node(node);
|
2123 | }
|
2124 | this.expand_to_depth(target_depth, node.children, depth + 1);
|
2125 | }
|
2126 | if (depth == target_depth) {
|
2127 | if (node.expanded) {
|
2128 | this.collapse_node(node);
|
2129 | }
|
2130 | }
|
2131 | }
|
2132 | },
|
2133 |
|
2134 | part_layout: function (node) {
|
2135 | var root = this.jm.mind.root;
|
2136 | if (!!root) {
|
2137 | var root_layout_data = root._data.layout;
|
2138 | if (node.isroot) {
|
2139 | root_layout_data.outer_height_right = this._layout_offset_subnodes_height(root_layout_data.right_nodes);
|
2140 | root_layout_data.outer_height_left = this._layout_offset_subnodes_height(root_layout_data.left_nodes);
|
2141 | } else {
|
2142 | if (node._data.layout.direction == jm.direction.right) {
|
2143 | root_layout_data.outer_height_right = this._layout_offset_subnodes_height(root_layout_data.right_nodes);
|
2144 | } else {
|
2145 | root_layout_data.outer_height_left = this._layout_offset_subnodes_height(root_layout_data.left_nodes);
|
2146 | }
|
2147 | }
|
2148 | this.bounds.s = Math.max(root_layout_data.outer_height_left, root_layout_data.outer_height_right);
|
2149 | this.cache_valid = false;
|
2150 | } else {
|
2151 | logger.warn('can not found root node');
|
2152 | }
|
2153 | },
|
2154 |
|
2155 | set_visible: function (nodes, visible) {
|
2156 | var i = nodes.length;
|
2157 | var node = null;
|
2158 | var layout_data = null;
|
2159 | while (i--) {
|
2160 | node = nodes[i];
|
2161 | layout_data = node._data.layout;
|
2162 | if (node.expanded) {
|
2163 | this.set_visible(node.children, visible);
|
2164 | } else {
|
2165 | this.set_visible(node.children, false);
|
2166 | }
|
2167 | if (!node.isroot) {
|
2168 | node._data.layout.visible = visible;
|
2169 | }
|
2170 | }
|
2171 | },
|
2172 |
|
2173 | is_expand: function (node) {
|
2174 | return node.expanded;
|
2175 | },
|
2176 |
|
2177 | is_visible: function (node) {
|
2178 | var layout_data = node._data.layout;
|
2179 | if (('visible' in layout_data) && !layout_data.visible) {
|
2180 | return false;
|
2181 | } else {
|
2182 | return true;
|
2183 | }
|
2184 | }
|
2185 | };
|
2186 |
|
2187 | jm.graph_canvas = function (view) {
|
2188 | this.opts = view.opts;
|
2189 | this.e_canvas = $c('canvas');
|
2190 | this.e_canvas.className = 'jsmind';
|
2191 | this.canvas_ctx = this.e_canvas.getContext('2d');
|
2192 | this.size = { w: 0, h: 0 };
|
2193 | };
|
2194 |
|
2195 | jm.graph_canvas.prototype = {
|
2196 | element: function () {
|
2197 | return this.e_canvas;
|
2198 | },
|
2199 |
|
2200 | set_size: function (w, h) {
|
2201 | this.size.w = w;
|
2202 | this.size.h = h;
|
2203 | this.e_canvas.width = w;
|
2204 | this.e_canvas.height = h;
|
2205 | },
|
2206 |
|
2207 | clear: function () {
|
2208 | this.canvas_ctx.clearRect(0, 0, this.size.w, this.size.h);
|
2209 | },
|
2210 |
|
2211 | draw_line: function (pout, pin, offset) {
|
2212 | var ctx = this.canvas_ctx;
|
2213 | ctx.strokeStyle = this.opts.line_color;
|
2214 | ctx.lineWidth = this.opts.line_width;
|
2215 | ctx.lineCap = 'round';
|
2216 |
|
2217 | this._bezier_to(ctx,
|
2218 | pin.x + offset.x,
|
2219 | pin.y + offset.y,
|
2220 | pout.x + offset.x,
|
2221 | pout.y + offset.y);
|
2222 | },
|
2223 |
|
2224 | copy_to: function (dest_canvas_ctx, callback) {
|
2225 | dest_canvas_ctx.drawImage(this.e_canvas, 0, 0);
|
2226 | !!callback && callback();
|
2227 | },
|
2228 |
|
2229 | _bezier_to: function (ctx, x1, y1, x2, y2) {
|
2230 | ctx.beginPath();
|
2231 | ctx.moveTo(x1, y1);
|
2232 | ctx.bezierCurveTo(x1 + (x2 - x1) * 2 / 3, y1, x1, y2, x2, y2);
|
2233 | ctx.stroke();
|
2234 | },
|
2235 |
|
2236 | _line_to: function (ctx, x1, y1, x2, y2) {
|
2237 | ctx.beginPath();
|
2238 | ctx.moveTo(x1, y1);
|
2239 | ctx.lineTo(x2, y2);
|
2240 | ctx.stroke();
|
2241 | }
|
2242 | };
|
2243 |
|
2244 | jm.graph_svg = function (view) {
|
2245 | this.view = view;
|
2246 | this.opts = view.opts;
|
2247 | this.e_svg = jm.graph_svg.c('svg');
|
2248 | this.e_svg.setAttribute('class', 'jsmind');
|
2249 | this.size = { w: 0, h: 0 };
|
2250 | this.lines = [];
|
2251 | };
|
2252 |
|
2253 | jm.graph_svg.c = function (tag) {
|
2254 | return $d.createElementNS('http://www.w3.org/2000/svg', tag);
|
2255 | };
|
2256 |
|
2257 | jm.graph_svg.prototype = {
|
2258 | element: function () {
|
2259 | return this.e_svg;
|
2260 | },
|
2261 |
|
2262 | set_size: function (w, h) {
|
2263 | this.size.w = w;
|
2264 | this.size.h = h;
|
2265 | this.e_svg.setAttribute('width', w);
|
2266 | this.e_svg.setAttribute('height', h);
|
2267 | },
|
2268 |
|
2269 | clear: function () {
|
2270 | var len = this.lines.length;
|
2271 | while (len--) {
|
2272 | this.e_svg.removeChild(this.lines[len]);
|
2273 | }
|
2274 | this.lines.length = 0;
|
2275 | },
|
2276 |
|
2277 | draw_line: function (pout, pin, offset) {
|
2278 | var line = jm.graph_svg.c('path');
|
2279 | line.setAttribute('stroke', this.opts.line_color);
|
2280 | line.setAttribute('stroke-width', this.opts.line_width);
|
2281 | line.setAttribute('fill', 'transparent');
|
2282 | this.lines.push(line);
|
2283 | this.e_svg.appendChild(line);
|
2284 | this._bezier_to(line, pin.x + offset.x, pin.y + offset.y, pout.x + offset.x, pout.y + offset.y);
|
2285 | },
|
2286 |
|
2287 | copy_to: function (dest_canvas_ctx, callback) {
|
2288 | var img = new Image();
|
2289 | img.onload = function () {
|
2290 | dest_canvas_ctx.drawImage(img, 0, 0);
|
2291 | !!callback && callback();
|
2292 | }
|
2293 | img.src = 'data:image/svg+xml;base64,' + btoa(new XMLSerializer().serializeToString(this.e_svg));
|
2294 | },
|
2295 |
|
2296 | _bezier_to: function (path, x1, y1, x2, y2) {
|
2297 | path.setAttribute('d', 'M' + x1 + ' ' + y1 + ' C ' + (x1 + (x2 - x1) * 2 / 3) + ' ' + y1 + ', ' + x1 + ' ' + y2 + ', ' + x2 + ' ' + y2);
|
2298 | },
|
2299 |
|
2300 | _line_to: function (path, x1, y1, x2, y2) {
|
2301 | path.setAttribute('d', 'M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2);
|
2302 | }
|
2303 | };
|
2304 |
|
2305 |
|
2306 | jm.view_provider = function (jm, options) {
|
2307 | this.opts = options;
|
2308 | this.jm = jm;
|
2309 | this.layout = jm.layout;
|
2310 |
|
2311 | this.container = null;
|
2312 | this.e_panel = null;
|
2313 | this.e_nodes = null;
|
2314 |
|
2315 | this.size = { w: 0, h: 0 };
|
2316 |
|
2317 | this.selected_node = null;
|
2318 | this.editing_node = null;
|
2319 |
|
2320 | this.graph = null;
|
2321 | };
|
2322 |
|
2323 | jm.view_provider.prototype = {
|
2324 | init: function () {
|
2325 | logger.debug('view.init');
|
2326 |
|
2327 | this.container = $i(this.opts.container) ? this.opts.container : $g(this.opts.container);
|
2328 | if (!this.container) {
|
2329 | logger.error('the options.view.container was not be found in dom');
|
2330 | return;
|
2331 | }
|
2332 | this.e_panel = $c('div');
|
2333 | this.e_nodes = $c('jmnodes');
|
2334 | this.e_editor = $c('input');
|
2335 |
|
2336 | this.graph = this.opts.engine.toLowerCase() === 'svg' ? new jm.graph_svg(this) : new jm.graph_canvas(this);
|
2337 | this.e_panel.className = 'jsmind-inner jmnode-overflow-' + this.opts.node_overflow;
|
2338 | this.e_panel.tabIndex = 1;
|
2339 | this.e_panel.appendChild(this.graph.element());
|
2340 | this.e_panel.appendChild(this.e_nodes);
|
2341 |
|
2342 | this.e_editor.className = 'jsmind-editor';
|
2343 | this.e_editor.type = 'text';
|
2344 |
|
2345 | this.actualZoom = 1;
|
2346 | this.zoomStep = 0.1;
|
2347 | this.minZoom = 0.5;
|
2348 | this.maxZoom = 2;
|
2349 |
|
2350 | var v = this;
|
2351 | jm.util.dom.add_event(this.e_editor, 'keydown', function (e) {
|
2352 | var evt = e || event;
|
2353 | if (evt.keyCode == 13) { v.edit_node_end(); evt.stopPropagation(); }
|
2354 | });
|
2355 | jm.util.dom.add_event(this.e_editor, 'blur', function (e) {
|
2356 | v.edit_node_end();
|
2357 | });
|
2358 |
|
2359 | this.container.appendChild(this.e_panel);
|
2360 |
|
2361 |
|
2362 | this.dragging_enabled = true
|
2363 |
|
2364 | this.draggable_canvas()
|
2365 | },
|
2366 |
|
2367 | add_event: function (obj, event_name, event_handle) {
|
2368 | jm.util.dom.add_event(this.e_nodes, event_name, function (e) {
|
2369 | var evt = e || event;
|
2370 | event_handle.call(obj, evt);
|
2371 | });
|
2372 | },
|
2373 |
|
2374 | get_binded_nodeid: function (element) {
|
2375 | if (element == null) {
|
2376 | return null;
|
2377 | }
|
2378 | var tagName = element.tagName.toLowerCase();
|
2379 | if (tagName == 'jmnode' || tagName == 'jmexpander') {
|
2380 | return element.getAttribute('nodeid');
|
2381 | } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {
|
2382 | return null;
|
2383 | } else {
|
2384 | return this.get_binded_nodeid(element.parentElement);
|
2385 | }
|
2386 | },
|
2387 |
|
2388 | is_node: function (element) {
|
2389 | if (element == null) {
|
2390 | return false;
|
2391 | }
|
2392 | var tagName = element.tagName.toLowerCase();
|
2393 | if (tagName == 'jmnode') {
|
2394 | return true;
|
2395 | } else if (tagName == 'jmnodes' || tagName == 'body' || tagName == 'html') {
|
2396 | return false;
|
2397 | } else {
|
2398 | return this.is_node(element.parentElement);
|
2399 | }
|
2400 | },
|
2401 |
|
2402 | is_expander: function (element) {
|
2403 | return (element.tagName.toLowerCase() == 'jmexpander');
|
2404 | },
|
2405 |
|
2406 | reset: function () {
|
2407 | logger.debug('view.reset');
|
2408 | this.selected_node = null;
|
2409 | this.clear_lines();
|
2410 | this.clear_nodes();
|
2411 | this.reset_theme();
|
2412 | },
|
2413 |
|
2414 | reset_theme: function () {
|
2415 | var theme_name = this.jm.options.theme;
|
2416 | if (!!theme_name) {
|
2417 | this.e_nodes.className = 'theme-' + theme_name;
|
2418 | } else {
|
2419 | this.e_nodes.className = '';
|
2420 | }
|
2421 | },
|
2422 |
|
2423 | reset_custom_style: function () {
|
2424 | var nodes = this.jm.mind.nodes;
|
2425 | for (var nodeid in nodes) {
|
2426 | this.reset_node_custom_style(nodes[nodeid]);
|
2427 | }
|
2428 | },
|
2429 |
|
2430 | load: function () {
|
2431 | logger.debug('view.load');
|
2432 | this.init_nodes();
|
2433 | },
|
2434 |
|
2435 | expand_size: function () {
|
2436 | var min_size = this.layout.get_min_size();
|
2437 | var min_width = min_size.w + this.opts.hmargin * 2;
|
2438 | var min_height = min_size.h + this.opts.vmargin * 2;
|
2439 | var client_w = this.e_panel.clientWidth;
|
2440 | var client_h = this.e_panel.clientHeight;
|
2441 | if (client_w < min_width) { client_w = min_width; }
|
2442 | if (client_h < min_height) { client_h = min_height; }
|
2443 | this.size.w = client_w;
|
2444 | this.size.h = client_h;
|
2445 | },
|
2446 |
|
2447 | init_nodes_size: function (node) {
|
2448 | var view_data = node._data.view;
|
2449 | view_data.width = view_data.element.clientWidth;
|
2450 | view_data.height = view_data.element.clientHeight;
|
2451 | },
|
2452 |
|
2453 | init_nodes: function () {
|
2454 | var nodes = this.jm.mind.nodes;
|
2455 | var doc_frag = $d.createDocumentFragment();
|
2456 | for (var nodeid in nodes) {
|
2457 | this.create_node_element(nodes[nodeid], doc_frag);
|
2458 | }
|
2459 | this.e_nodes.appendChild(doc_frag);
|
2460 | for (var nodeid in nodes) {
|
2461 | this.init_nodes_size(nodes[nodeid]);
|
2462 | }
|
2463 | },
|
2464 |
|
2465 | add_node: function (node) {
|
2466 | this.create_node_element(node, this.e_nodes);
|
2467 | this.init_nodes_size(node);
|
2468 | },
|
2469 |
|
2470 | create_node_element: function (node, parent_node) {
|
2471 | var view_data = null;
|
2472 | if ('view' in node._data) {
|
2473 | view_data = node._data.view;
|
2474 | } else {
|
2475 | view_data = {};
|
2476 | node._data.view = view_data;
|
2477 | }
|
2478 |
|
2479 | var d = $c('jmnode');
|
2480 | if (node.isroot) {
|
2481 | d.className = 'root';
|
2482 | } else {
|
2483 | var d_e = $c('jmexpander');
|
2484 | $t(d_e, '-');
|
2485 | d_e.setAttribute('nodeid', node.id);
|
2486 | d_e.style.visibility = 'hidden';
|
2487 | parent_node.appendChild(d_e);
|
2488 | view_data.expander = d_e;
|
2489 | }
|
2490 | if (!!node.topic) {
|
2491 | if (this.opts.support_html) {
|
2492 | $h(d, node.topic);
|
2493 | } else {
|
2494 | $t(d, node.topic);
|
2495 | }
|
2496 | }
|
2497 | d.setAttribute('nodeid', node.id);
|
2498 | d.style.visibility = 'hidden';
|
2499 | this._reset_node_custom_style(d, node.data);
|
2500 |
|
2501 | parent_node.appendChild(d);
|
2502 | view_data.element = d;
|
2503 | },
|
2504 |
|
2505 | remove_node: function (node) {
|
2506 | if (this.selected_node != null && this.selected_node.id == node.id) {
|
2507 | this.selected_node = null;
|
2508 | }
|
2509 | if (this.editing_node != null && this.editing_node.id == node.id) {
|
2510 | node._data.view.element.removeChild(this.e_editor);
|
2511 | this.editing_node = null;
|
2512 | }
|
2513 | var children = node.children;
|
2514 | var i = children.length;
|
2515 | while (i--) {
|
2516 | this.remove_node(children[i]);
|
2517 | }
|
2518 | if (node._data.view) {
|
2519 | var element = node._data.view.element;
|
2520 | var expander = node._data.view.expander;
|
2521 | this.e_nodes.removeChild(element);
|
2522 | this.e_nodes.removeChild(expander);
|
2523 | node._data.view.element = null;
|
2524 | node._data.view.expander = null;
|
2525 | }
|
2526 | },
|
2527 |
|
2528 | update_node: function (node) {
|
2529 | var view_data = node._data.view;
|
2530 | var element = view_data.element;
|
2531 | if (!!node.topic) {
|
2532 | if (this.opts.support_html) {
|
2533 | $h(element, node.topic);
|
2534 | } else {
|
2535 | $t(element, node.topic);
|
2536 | }
|
2537 | }
|
2538 | if (this.layout.is_visible(node)) {
|
2539 | view_data.width = element.clientWidth;
|
2540 | view_data.height = element.clientHeight;
|
2541 | } else {
|
2542 | let origin_style = element.getAttribute('style');
|
2543 | element.style = 'visibility: visible; left:0; top:0;';
|
2544 | view_data.width = element.clientWidth;
|
2545 | view_data.height = element.clientHeight;
|
2546 | element.style = origin_style;
|
2547 | }
|
2548 | },
|
2549 |
|
2550 | select_node: function (node) {
|
2551 | if (!!this.selected_node) {
|
2552 | this.selected_node._data.view.element.className =
|
2553 | this.selected_node._data.view.element.className.replace(/\s*selected\b/i, '');
|
2554 | this.reset_node_custom_style(this.selected_node);
|
2555 | }
|
2556 | if (!!node) {
|
2557 | this.selected_node = node;
|
2558 | node._data.view.element.className += ' selected';
|
2559 | this.clear_node_custom_style(node);
|
2560 | }
|
2561 | },
|
2562 |
|
2563 | select_clear: function () {
|
2564 | this.select_node(null);
|
2565 | },
|
2566 |
|
2567 | get_editing_node: function () {
|
2568 | return this.editing_node;
|
2569 | },
|
2570 |
|
2571 | is_editing: function () {
|
2572 | return (!!this.editing_node);
|
2573 | },
|
2574 |
|
2575 | edit_node_begin: function (node) {
|
2576 | if (!node.topic) {
|
2577 | logger.warn("don't edit image nodes");
|
2578 | return;
|
2579 | }
|
2580 | if (this.editing_node != null) {
|
2581 | this.edit_node_end();
|
2582 | }
|
2583 | this.editing_node = node;
|
2584 | var view_data = node._data.view;
|
2585 | var element = view_data.element;
|
2586 | var topic = node.topic;
|
2587 | var ncs = getComputedStyle(element);
|
2588 | this.e_editor.value = topic;
|
2589 | this.e_editor.style.width = (element.clientWidth - parseInt(ncs.getPropertyValue('padding-left')) - parseInt(ncs.getPropertyValue('padding-right'))) + 'px';
|
2590 | element.innerHTML = '';
|
2591 | element.appendChild(this.e_editor);
|
2592 | element.style.zIndex = 5;
|
2593 | this.e_editor.focus();
|
2594 | this.e_editor.select();
|
2595 | },
|
2596 |
|
2597 | edit_node_end: function () {
|
2598 | if (this.editing_node != null) {
|
2599 | var node = this.editing_node;
|
2600 | this.editing_node = null;
|
2601 | var view_data = node._data.view;
|
2602 | var element = view_data.element;
|
2603 | var topic = this.e_editor.value;
|
2604 | element.style.zIndex = 'auto';
|
2605 | element.removeChild(this.e_editor);
|
2606 | if (jm.util.text.is_empty(topic) || node.topic === topic) {
|
2607 | if (this.opts.support_html) {
|
2608 | $h(element, node.topic);
|
2609 | } else {
|
2610 | $t(element, node.topic);
|
2611 | }
|
2612 | } else {
|
2613 | this.jm.update_node(node.id, topic);
|
2614 | }
|
2615 | }
|
2616 | this.e_panel.focus();
|
2617 | },
|
2618 |
|
2619 | get_view_offset: function () {
|
2620 | var bounds = this.layout.bounds;
|
2621 | var _x = (this.size.w - bounds.e - bounds.w) / 2;
|
2622 | var _y = this.size.h / 2;
|
2623 | return { x: _x, y: _y };
|
2624 | },
|
2625 |
|
2626 | resize: function () {
|
2627 | this.graph.set_size(1, 1);
|
2628 | this.e_nodes.style.width = '1px';
|
2629 | this.e_nodes.style.height = '1px';
|
2630 |
|
2631 | this.expand_size();
|
2632 | this._show();
|
2633 | },
|
2634 |
|
2635 | _show: function () {
|
2636 | this.graph.set_size(this.size.w, this.size.h);
|
2637 | this.e_nodes.style.width = this.size.w + 'px';
|
2638 | this.e_nodes.style.height = this.size.h + 'px';
|
2639 | this.show_nodes();
|
2640 | this.show_lines();
|
2641 |
|
2642 | this.jm.invoke_event_handle(jm.event_type.resize, { data: [] });
|
2643 | },
|
2644 |
|
2645 | zoomIn: function () {
|
2646 | return this.setZoom(this.actualZoom + this.zoomStep);
|
2647 | },
|
2648 |
|
2649 | zoomOut: function () {
|
2650 | return this.setZoom(this.actualZoom - this.zoomStep);
|
2651 | },
|
2652 |
|
2653 | setZoom: function (zoom) {
|
2654 | if ((zoom < this.minZoom) || (zoom > this.maxZoom)) {
|
2655 | return false;
|
2656 | }
|
2657 | this.actualZoom = zoom;
|
2658 | for (var i = 0; i < this.e_panel.children.length; i++) {
|
2659 | this.e_panel.children[i].style.zoom = zoom;
|
2660 | };
|
2661 | this.show(true);
|
2662 | return true;
|
2663 |
|
2664 | },
|
2665 |
|
2666 | _center_root: function () {
|
2667 |
|
2668 | var outer_w = this.e_panel.clientWidth;
|
2669 | var outer_h = this.e_panel.clientHeight;
|
2670 | if (this.size.w > outer_w) {
|
2671 | var _offset = this.get_view_offset();
|
2672 | this.e_panel.scrollLeft = _offset.x * this.actualZoom - outer_w / 2;
|
2673 | }
|
2674 | if (this.size.h > outer_h) {
|
2675 | this.e_panel.scrollTop = (this.size.h * this.actualZoom - outer_h) / 2;
|
2676 | }
|
2677 | },
|
2678 |
|
2679 | show: function (keep_center) {
|
2680 | logger.debug('view.show');
|
2681 | this.expand_size();
|
2682 | this._show();
|
2683 | if (!!keep_center) {
|
2684 | this._center_root();
|
2685 | }
|
2686 | },
|
2687 |
|
2688 | relayout: function () {
|
2689 | this.expand_size();
|
2690 | this._show();
|
2691 | },
|
2692 |
|
2693 | save_location: function (node) {
|
2694 | var vd = node._data.view;
|
2695 | vd._saved_location = {
|
2696 | x: parseInt(vd.element.style.left) - this.e_panel.scrollLeft,
|
2697 | y: parseInt(vd.element.style.top) - this.e_panel.scrollTop,
|
2698 | };
|
2699 | },
|
2700 |
|
2701 | restore_location: function (node) {
|
2702 | var vd = node._data.view;
|
2703 | this.e_panel.scrollLeft = parseInt(vd.element.style.left) - vd._saved_location.x;
|
2704 | this.e_panel.scrollTop = parseInt(vd.element.style.top) - vd._saved_location.y;
|
2705 | },
|
2706 |
|
2707 | clear_nodes: function () {
|
2708 | var mind = this.jm.mind;
|
2709 | if (mind == null) {
|
2710 | return;
|
2711 | }
|
2712 | var nodes = mind.nodes;
|
2713 | var node = null;
|
2714 | for (var nodeid in nodes) {
|
2715 | node = nodes[nodeid];
|
2716 | node._data.view.element = null;
|
2717 | node._data.view.expander = null;
|
2718 | }
|
2719 | this.e_nodes.innerHTML = '';
|
2720 | },
|
2721 |
|
2722 | show_nodes: function () {
|
2723 | var nodes = this.jm.mind.nodes;
|
2724 | var node = null;
|
2725 | var node_element = null;
|
2726 | var expander = null;
|
2727 | var p = null;
|
2728 | var p_expander = null;
|
2729 | var expander_text = '-';
|
2730 | var view_data = null;
|
2731 | var _offset = this.get_view_offset();
|
2732 | for (var nodeid in nodes) {
|
2733 | node = nodes[nodeid];
|
2734 | view_data = node._data.view;
|
2735 | node_element = view_data.element;
|
2736 | expander = view_data.expander;
|
2737 | if (!this.layout.is_visible(node)) {
|
2738 | node_element.style.display = 'none';
|
2739 | expander.style.display = 'none';
|
2740 | continue;
|
2741 | }
|
2742 | this.reset_node_custom_style(node);
|
2743 | p = this.layout.get_node_point(node);
|
2744 | view_data.abs_x = _offset.x + p.x;
|
2745 | view_data.abs_y = _offset.y + p.y;
|
2746 | node_element.style.left = (_offset.x + p.x) + 'px';
|
2747 | node_element.style.top = (_offset.y + p.y) + 'px';
|
2748 | node_element.style.display = '';
|
2749 | node_element.style.visibility = 'visible';
|
2750 | if (!node.isroot && node.children.length > 0) {
|
2751 | expander_text = node.expanded ? '-' : '+';
|
2752 | p_expander = this.layout.get_expander_point(node);
|
2753 | expander.style.left = (_offset.x + p_expander.x) + 'px';
|
2754 | expander.style.top = (_offset.y + p_expander.y) + 'px';
|
2755 | expander.style.display = '';
|
2756 | expander.style.visibility = 'visible';
|
2757 | $t(expander, expander_text);
|
2758 | }
|
2759 |
|
2760 | if (!node.isroot && node.children.length == 0) {
|
2761 | expander.style.display = 'none';
|
2762 | expander.style.visibility = 'hidden';
|
2763 | }
|
2764 | }
|
2765 | },
|
2766 |
|
2767 | reset_node_custom_style: function (node) {
|
2768 | this._reset_node_custom_style(node._data.view.element, node.data);
|
2769 | },
|
2770 |
|
2771 | _reset_node_custom_style: function (node_element, node_data) {
|
2772 | if ('background-color' in node_data) {
|
2773 | node_element.style.backgroundColor = node_data['background-color'];
|
2774 | }
|
2775 | if ('foreground-color' in node_data) {
|
2776 | node_element.style.color = node_data['foreground-color'];
|
2777 | }
|
2778 | if ('width' in node_data) {
|
2779 | node_element.style.width = node_data['width'] + 'px';
|
2780 | }
|
2781 | if ('height' in node_data) {
|
2782 | node_element.style.height = node_data['height'] + 'px';
|
2783 | }
|
2784 | if ('font-size' in node_data) {
|
2785 | node_element.style.fontSize = node_data['font-size'] + 'px';
|
2786 | }
|
2787 | if ('font-weight' in node_data) {
|
2788 | node_element.style.fontWeight = node_data['font-weight'];
|
2789 | }
|
2790 | if ('font-style' in node_data) {
|
2791 | node_element.style.fontStyle = node_data['font-style'];
|
2792 | }
|
2793 | if ('background-image' in node_data) {
|
2794 | var backgroundImage = node_data['background-image'];
|
2795 | if (backgroundImage.startsWith('data') && node_data['width'] && node_data['height']) {
|
2796 | var img = new Image();
|
2797 |
|
2798 | img.onload = function () {
|
2799 | var c = $c('canvas');
|
2800 | c.width = node_element.clientWidth;
|
2801 | c.height = node_element.clientHeight;
|
2802 | var img = this;
|
2803 | if (c.getContext) {
|
2804 | var ctx = c.getContext('2d');
|
2805 | ctx.drawImage(img, 2, 2, node_element.clientWidth, node_element.clientHeight);
|
2806 | var scaledImageData = c.toDataURL();
|
2807 | node_element.style.backgroundImage = 'url(' + scaledImageData + ')';
|
2808 | }
|
2809 | };
|
2810 | img.src = backgroundImage;
|
2811 |
|
2812 | } else {
|
2813 | node_element.style.backgroundImage = 'url(' + backgroundImage + ')';
|
2814 | }
|
2815 | node_element.style.backgroundSize = '99%';
|
2816 |
|
2817 | if ('background-rotation' in node_data) {
|
2818 | node_element.style.transform = 'rotate(' + node_data['background-rotation'] + 'deg)';
|
2819 | }
|
2820 | }
|
2821 | },
|
2822 |
|
2823 | clear_node_custom_style: function (node) {
|
2824 | var node_element = node._data.view.element;
|
2825 | node_element.style.backgroundColor = "";
|
2826 | node_element.style.color = "";
|
2827 | },
|
2828 |
|
2829 | clear_lines: function () {
|
2830 | this.graph.clear();
|
2831 | },
|
2832 |
|
2833 | show_lines: function () {
|
2834 | this.clear_lines();
|
2835 | var nodes = this.jm.mind.nodes;
|
2836 | var node = null;
|
2837 | var pin = null;
|
2838 | var pout = null;
|
2839 | var _offset = this.get_view_offset();
|
2840 | for (var nodeid in nodes) {
|
2841 | node = nodes[nodeid];
|
2842 | if (!!node.isroot) { continue; }
|
2843 | if (('visible' in node._data.layout) && !node._data.layout.visible) { continue; }
|
2844 | pin = this.layout.get_node_point_in(node);
|
2845 | pout = this.layout.get_node_point_out(node.parent);
|
2846 | this.graph.draw_line(pout, pin, _offset);
|
2847 | }
|
2848 | },
|
2849 |
|
2850 |
|
2851 | draggable_canvas: function () {
|
2852 |
|
2853 | if (this.opts.draggable) {
|
2854 |
|
2855 | let dragging = false
|
2856 | let x, y
|
2857 | if (this.opts.hide_scrollbars_when_draggable) {
|
2858 |
|
2859 | this.e_panel.style = 'overflow: hidden'
|
2860 | }
|
2861 |
|
2862 | jm.util.dom.add_event(this.container, 'mousedown', (eventDown) => {
|
2863 | dragging = true
|
2864 |
|
2865 | x = eventDown.clientX
|
2866 | y = eventDown.clientY
|
2867 | })
|
2868 |
|
2869 | jm.util.dom.add_event(this.container, 'mouseup', () => {
|
2870 | dragging = false
|
2871 | })
|
2872 |
|
2873 | jm.util.dom.add_event(this.container, 'mousemove', (eventMove) => {
|
2874 | if (this.dragging_enabled && dragging) {
|
2875 | this.e_panel.scrollBy(x - eventMove.clientX, y - eventMove.clientY)
|
2876 |
|
2877 | x = eventMove.clientX
|
2878 | y = eventMove.clientY
|
2879 | }
|
2880 | })
|
2881 | }
|
2882 | },
|
2883 |
|
2884 | get_draggable_canvas: function () {
|
2885 | return this.opts.draggable
|
2886 | },
|
2887 |
|
2888 | enable_draggable_canvas: function () {
|
2889 | this.dragging_enabled = true
|
2890 | },
|
2891 |
|
2892 | disable_draggable_canvas: function () {
|
2893 | this.dragging_enabled = false
|
2894 | },
|
2895 |
|
2896 | };
|
2897 |
|
2898 |
|
2899 | jm.shortcut_provider = function (jm, options) {
|
2900 | this.jm = jm;
|
2901 | this.opts = options;
|
2902 | this.mapping = options.mapping;
|
2903 | this.handles = options.handles;
|
2904 | this._newid = null;
|
2905 | this._mapping = {};
|
2906 | };
|
2907 |
|
2908 | jm.shortcut_provider.prototype = {
|
2909 | init: function () {
|
2910 | jm.util.dom.add_event(this.jm.view.e_panel, 'keydown', this.handler.bind(this));
|
2911 |
|
2912 | this.handles['addchild'] = this.handle_addchild;
|
2913 | this.handles['addbrother'] = this.handle_addbrother;
|
2914 | this.handles['editnode'] = this.handle_editnode;
|
2915 | this.handles['delnode'] = this.handle_delnode;
|
2916 | this.handles['toggle'] = this.handle_toggle;
|
2917 | this.handles['up'] = this.handle_up;
|
2918 | this.handles['down'] = this.handle_down;
|
2919 | this.handles['left'] = this.handle_left;
|
2920 | this.handles['right'] = this.handle_right;
|
2921 |
|
2922 | for (var handle in this.mapping) {
|
2923 | if (!!this.mapping[handle] && (handle in this.handles)) {
|
2924 | var keys = this.mapping[handle];
|
2925 | if(!Array.isArray(keys)){
|
2926 | keys = [keys]
|
2927 | }
|
2928 | for(let key of keys){
|
2929 | this._mapping[key] = this.handles[handle];
|
2930 | }
|
2931 | }
|
2932 | }
|
2933 |
|
2934 | if (typeof this.opts.id_generator === 'function') {
|
2935 | this._newid = this.opts.id_generator;
|
2936 | } else {
|
2937 | this._newid = jm.util.uuid.newid;
|
2938 | }
|
2939 | },
|
2940 |
|
2941 | enable_shortcut: function () {
|
2942 | this.opts.enable = true;
|
2943 | },
|
2944 |
|
2945 | disable_shortcut: function () {
|
2946 | this.opts.enable = false;
|
2947 | },
|
2948 |
|
2949 | handler: function (e) {
|
2950 | if (e.which == 9) { e.preventDefault(); }
|
2951 | if (this.jm.view.is_editing()) { return; }
|
2952 | var evt = e || event;
|
2953 | if (!this.opts.enable) { return true; }
|
2954 | var kc = evt.keyCode + (evt.metaKey << 13) + (evt.ctrlKey << 12) + (evt.altKey << 11) + (evt.shiftKey << 10);
|
2955 | if (kc in this._mapping) {
|
2956 | this._mapping[kc].call(this, this.jm, e);
|
2957 | }
|
2958 | },
|
2959 |
|
2960 | handle_addchild: function (_jm, e) {
|
2961 | var selected_node = _jm.get_selected_node();
|
2962 | if (!!selected_node) {
|
2963 | var nodeid = this._newid();
|
2964 | var node = _jm.add_node(selected_node, nodeid, 'New Node');
|
2965 | if (!!node) {
|
2966 | _jm.select_node(nodeid);
|
2967 | _jm.begin_edit(nodeid);
|
2968 | }
|
2969 | }
|
2970 | },
|
2971 | handle_addbrother: function (_jm, e) {
|
2972 | var selected_node = _jm.get_selected_node();
|
2973 | if (!!selected_node && !selected_node.isroot) {
|
2974 | var nodeid = this._newid();
|
2975 | var node = _jm.insert_node_after(selected_node, nodeid, 'New Node');
|
2976 | if (!!node) {
|
2977 | _jm.select_node(nodeid);
|
2978 | _jm.begin_edit(nodeid);
|
2979 | }
|
2980 | }
|
2981 | },
|
2982 | handle_editnode: function (_jm, e) {
|
2983 | var selected_node = _jm.get_selected_node();
|
2984 | if (!!selected_node) {
|
2985 | _jm.begin_edit(selected_node);
|
2986 | }
|
2987 | },
|
2988 | handle_delnode: function (_jm, e) {
|
2989 | var selected_node = _jm.get_selected_node();
|
2990 | if (!!selected_node && !selected_node.isroot) {
|
2991 | _jm.select_node(selected_node.parent);
|
2992 | _jm.remove_node(selected_node);
|
2993 | }
|
2994 | },
|
2995 | handle_toggle: function (_jm, e) {
|
2996 | var evt = e || event;
|
2997 | var selected_node = _jm.get_selected_node();
|
2998 | if (!!selected_node) {
|
2999 | _jm.toggle_node(selected_node.id);
|
3000 | evt.stopPropagation();
|
3001 | evt.preventDefault();
|
3002 | }
|
3003 | },
|
3004 | handle_up: function (_jm, e) {
|
3005 | var evt = e || event;
|
3006 | var selected_node = _jm.get_selected_node();
|
3007 | if (!!selected_node) {
|
3008 | var up_node = _jm.find_node_before(selected_node);
|
3009 | if (!up_node) {
|
3010 | var np = _jm.find_node_before(selected_node.parent);
|
3011 | if (!!np && np.children.length > 0) {
|
3012 | up_node = np.children[np.children.length - 1];
|
3013 | }
|
3014 | }
|
3015 | if (!!up_node) {
|
3016 | _jm.select_node(up_node);
|
3017 | }
|
3018 | evt.stopPropagation();
|
3019 | evt.preventDefault();
|
3020 | }
|
3021 | },
|
3022 |
|
3023 | handle_down: function (_jm, e) {
|
3024 | var evt = e || event;
|
3025 | var selected_node = _jm.get_selected_node();
|
3026 | if (!!selected_node) {
|
3027 | var down_node = _jm.find_node_after(selected_node);
|
3028 | if (!down_node) {
|
3029 | var np = _jm.find_node_after(selected_node.parent);
|
3030 | if (!!np && np.children.length > 0) {
|
3031 | down_node = np.children[0];
|
3032 | }
|
3033 | }
|
3034 | if (!!down_node) {
|
3035 | _jm.select_node(down_node);
|
3036 | }
|
3037 | evt.stopPropagation();
|
3038 | evt.preventDefault();
|
3039 | }
|
3040 | },
|
3041 |
|
3042 | handle_left: function (_jm, e) {
|
3043 | this._handle_direction(_jm, e, jm.direction.left);
|
3044 | },
|
3045 | handle_right: function (_jm, e) {
|
3046 | this._handle_direction(_jm, e, jm.direction.right);
|
3047 | },
|
3048 | _handle_direction: function (_jm, e, d) {
|
3049 | var evt = e || event;
|
3050 | var selected_node = _jm.get_selected_node();
|
3051 | var node = null;
|
3052 | if (!!selected_node) {
|
3053 | if (selected_node.isroot) {
|
3054 | var c = selected_node.children;
|
3055 | var children = [];
|
3056 | for (var i = 0; i < c.length; i++) {
|
3057 | if (c[i].direction === d) {
|
3058 | children.push(i);
|
3059 | }
|
3060 | }
|
3061 | node = c[children[Math.floor((children.length - 1) / 2)]];
|
3062 | }
|
3063 | else if (selected_node.direction === d) {
|
3064 | var children = selected_node.children;
|
3065 | var childrencount = children.length;
|
3066 | if (childrencount > 0) {
|
3067 | node = children[Math.floor((childrencount - 1) / 2)];
|
3068 | }
|
3069 | } else {
|
3070 | node = selected_node.parent;
|
3071 | }
|
3072 | if (!!node) {
|
3073 | _jm.select_node(node);
|
3074 | }
|
3075 | evt.stopPropagation();
|
3076 | evt.preventDefault();
|
3077 | }
|
3078 | },
|
3079 | };
|
3080 |
|
3081 |
|
3082 |
|
3083 | jm.plugin = function (name, init) {
|
3084 | this.name = name;
|
3085 | this.init = init;
|
3086 | };
|
3087 |
|
3088 | jm.plugins = [];
|
3089 |
|
3090 | jm.register_plugin = function (plugin) {
|
3091 | if (plugin instanceof jm.plugin) {
|
3092 | jm.plugins.push(plugin);
|
3093 | }
|
3094 | };
|
3095 |
|
3096 | jm.init_plugins = function (sender) {
|
3097 | $w.setTimeout(function () {
|
3098 | jm._init_plugins(sender);
|
3099 | }, 0);
|
3100 | };
|
3101 |
|
3102 | jm._init_plugins = function (sender) {
|
3103 | var l = jm.plugins.length;
|
3104 | var fn_init = null;
|
3105 | for (var i = 0; i < l; i++) {
|
3106 | fn_init = jm.plugins[i].init;
|
3107 | if (typeof fn_init === 'function') {
|
3108 | fn_init(sender);
|
3109 | }
|
3110 | }
|
3111 | };
|
3112 |
|
3113 | jm.show = function (options, mind) {
|
3114 | logger.warn('`jsMind.show(options, mind)` is deprecated, please use `jm = new jsMind(options); jm.show(mind);` instead')
|
3115 | var _jm = new jm(options);
|
3116 | _jm.show(mind);
|
3117 | return _jm;
|
3118 | };
|
3119 |
|
3120 |
|
3121 | if (typeof module !== 'undefined' && typeof exports === 'object') {
|
3122 | module.exports = jm;
|
3123 | } else if (typeof define === 'function' && (define.amd || define.cmd)) {
|
3124 | define(function () { return jm; });
|
3125 | } else {
|
3126 | $w[__name__] = jm;
|
3127 | }
|
3128 | })(typeof window !== 'undefined' ? window : global);
|