Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

281 řádky
5.8 KiB

  1. define([
  2. 'js/tplNode',
  3. 'js/events',
  4. 'js/client',
  5. 'js/input'
  6. ], function (
  7. tplNode,
  8. events,
  9. client,
  10. input
  11. ) {
  12. return {
  13. links: [],
  14. nodes: [],
  15. mode: 'none',
  16. init: function () {
  17. events.on('onAreaSelect', this.events.onAreaSelect.bind(this));
  18. events.on('onMouseMove', this.events.onMouseMove.bind(this));
  19. },
  20. findNode: function (x, y) {
  21. var res = this.nodes.find(n => ((n.pos.x == x) && (n.pos.y == y)));
  22. if (!res) {
  23. res = this.nodes.find(function (n) {
  24. return ((n.size > 0) && (Math.abs(n.pos.x - x) <= 1) && (Math.abs(n.pos.y - y) <= 1))
  25. });
  26. }
  27. return res;
  28. },
  29. callAction: function (action, options = {}) {
  30. var node = options.node || this.findNode(options.x, options.y);
  31. options.node = node;
  32. return !this.actions[action].call(this, options);
  33. },
  34. getSelected: function (single) {
  35. var selected = this.nodes.filter(n => n.selected);
  36. if ((single) && (selected.length != 1))
  37. return null;
  38. if (single)
  39. return selected[0];
  40. else
  41. return selected;
  42. },
  43. serialize: function () {
  44. return JSON.stringify({
  45. nodes: this.nodes,
  46. links: this.links.map(function (l) {
  47. return {
  48. from: {
  49. id: l.from.id
  50. },
  51. to: {
  52. id: l.to.id
  53. }
  54. };
  55. })
  56. });
  57. },
  58. getNextId: function () {
  59. for (var i = 0; i < this.nodes.length; i++) {
  60. if (!this.nodes.some(n => (n.id == i)))
  61. return i;
  62. }
  63. return this.nodes.length;
  64. },
  65. setMode: function (mode) {
  66. this.mode = mode;
  67. },
  68. actions: {
  69. reset: function () {
  70. this.nodes = [];
  71. this.links = [];
  72. events.emit('onNew');
  73. },
  74. load: function (data) {
  75. this.nodes = data.nodes;
  76. this.nodes.forEach(function (n) {
  77. if ((n.group) && (!n.group.push))
  78. n.group = [n.group];
  79. });
  80. this.links = data.links.map(function (l) {
  81. l.from = this.nodes.find(n => (n.id == l.from.id));
  82. l.to = this.nodes.find(n => (n.id == l.to.id));
  83. return l;
  84. }, this);
  85. events.emit('onTreeLoaded', {
  86. nodes: this.nodes,
  87. links: this.links
  88. });
  89. },
  90. selectNode: function (options) {
  91. if (
  92. (
  93. (!options.node) ||
  94. (!this.nodes.some(n => ((n.selected) && (n == options.node))))
  95. ) &&
  96. (
  97. (!input.isKeyDown('shift')) ||
  98. (options.force)
  99. )
  100. )
  101. this.nodes.forEach(n => (n.selected = false));
  102. if (options.node)
  103. options.node.selected = true;
  104. else if (options instanceof Array)
  105. options.forEach(n => (n.selected = true));
  106. events.emit('onSelectNode', this.nodes.filter(n => n.selected));
  107. if (options.node)
  108. events.emit('onFocusNode', options.node);
  109. return !options.node;
  110. },
  111. addNode: function (options) {
  112. this.nodes.push(tplNode.build({
  113. id: this.getNextId(),
  114. x: options.x,
  115. y: options.y
  116. }));
  117. this.callAction('selectNode');
  118. },
  119. connectNode: function (options) {
  120. var node = options.node;
  121. if (!node) {
  122. this.callAction('selectNode');
  123. return true;
  124. }
  125. var singleSelected = this.getSelected(true);
  126. if ((singleSelected) && (input.isKeyDown('ctrl'))) {
  127. if (options.shiftDown) {
  128. this.links.spliceWhere(l => (
  129. (
  130. (l.from == node) ||
  131. (l.to == node)
  132. ) &&
  133. (
  134. (l.from == singleSelected) ||
  135. (l.to == singleSelected)
  136. ) &&
  137. (node != singleSelected)
  138. ));
  139. } else {
  140. this.links.push({
  141. from: singleSelected,
  142. to: node
  143. });
  144. }
  145. this.callAction('selectNode', {
  146. force: true
  147. });
  148. this.callAction('selectNode', {
  149. node: options.node
  150. });
  151. } else {
  152. return this.callAction('selectNode', {
  153. node: node
  154. })
  155. }
  156. },
  157. moveNode: function (options) {
  158. var selected = this.getSelected();
  159. if (!selected.length)
  160. return true;
  161. if (selected.length == 0)
  162. return;
  163. selected.sort(function (a, b) {
  164. var distanceA = Math.abs(a.pos.x - options.x) + Math.abs(a.pos.y - options.y);
  165. var distanceB = Math.abs(b.pos.x - options.x) + Math.abs(b.pos.y - options.y);
  166. return (distanceA > distanceB) ? 1 : -1;
  167. });
  168. var deltaX = selected[0].pos.x - options.x;
  169. var deltaY = selected[0].pos.y - options.y;
  170. selected.forEach(function (s) {
  171. s.pos.x -= deltaX;
  172. s.pos.y -= deltaY;
  173. });
  174. },
  175. deleteNode: function (options) {
  176. var selected = this.getSelected();
  177. selected.forEach(function (s) {
  178. this.nodes.spliceWhere(n => (n == s));
  179. this.links.spliceWhere(n => ((n.from == s) || (n.to == s)));
  180. s.selected = false;
  181. events.emit('onDeleteNode', s);
  182. }, this);
  183. },
  184. recolorNode: function () {
  185. var selected = this.getSelected(true);
  186. if (!selected)
  187. return true;
  188. selected.color = (selected.color + 1) % 7;
  189. },
  190. resizeNode: function () {
  191. var selected = this.getSelected(true);
  192. if (!selected)
  193. return true;
  194. selected.size = (selected.size + 1) % 3;
  195. }
  196. },
  197. events: {
  198. onAreaSelect: function (from, to) {
  199. if (!input.isKeyDown('ctrl'))
  200. this.nodes.forEach(n => (n.selected = false));
  201. var lowX = Math.min(from.x, to.x);
  202. var lowY = Math.min(from.y, to.y);
  203. var highX = Math.max(from.x, to.x);
  204. var highY = Math.max(from.y, to.y);
  205. for (var i = lowX; i <= highX; i++) {
  206. for (var j = lowY; j <= highY; j++) {
  207. var node = this.findNode(i, j);
  208. if (!node)
  209. continue;
  210. node.selected = true;
  211. }
  212. }
  213. events.emit('onSelectNode', this.nodes.filter(n => n.selected));
  214. },
  215. onMouseMove: function (e) {
  216. var hoverNode = this.findNode(e.x, e.y);
  217. if (hoverNode) {
  218. var text = '';
  219. var stats = hoverNode.stats || {};
  220. for (var s in stats) {
  221. text += s + ': ' + stats[s] + '<br />';
  222. }
  223. text = text.substr(0, text.length - 6);
  224. if (text.length > 0)
  225. events.emit('onShowTooltip', e, text);
  226. } else
  227. events.emit('onHideTooltip');
  228. }
  229. }
  230. };
  231. });