vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

659 lines
21 KiB

Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
9 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
Network: Fix handling of multi-fonts (#3486) * The next fix on Travis unit test failure This is the next escalation on the war against the Travis unit tests failing (which came into being by yours truly). By accident, I could recreate the unit test failure on my development machine. This led to a more directed effort to squash the bug. The insight here is that test `(window === undefined)` fails, but `(typeof window === 'undefined`)` succeeds. This undoubtedly has to do with the special status `window` has as a global object. Changes: - Added check on presence of `window` in `Canvas._requestNextFrame()`, fixed local source errors. - Added catch clause in `CanvasRendered._determinePixelRatio()` - small fix: raised timeout for the network `worldCup2014` unit test * Preliminary refactoring in utils.js * Added unit tests for extend routines, commenting and small fixes * More unit tests for extend routines * - Completed unit tests for extend routines in - Small fixes and cleanup in `util.js` - Removed `util.protoExtend()`, not used anywhere * Added unit tests for known font options * Interim save before trying out another proto chain strategy * Fixed problem in first example #3408 * Removed silly file that shouldn't be there * Added unit test for multi-fonts * Comment edits * Verufy unit tests, small adjustments for groups * Further work on getting unit tests to work. PARTS NEED TO BE CLEANED UP! * Further tweaks to get unit tests working * All unit tests passing * Fixes due to linting * Small edits * Removed prototype handling from font pile * Fixes during testing examples of #3408 * Added unit test for edge labels, small fixes * Added unit tests for shorthand string fonts; some tests still failing * All unit tests pass * Removed Label.parseOptions() * Completed shorthand font tests, code cleanup, fixed choosify for edges * Addressed review comments * Addressed review comments, cleanup
7 years ago
9 years ago
9 years ago
  1. var util = require('../../../util');
  2. var Label = require('./shared/Label').default;
  3. var ComponentUtil = require('./shared/ComponentUtil').default;
  4. var Box = require('./nodes/shapes/Box').default;
  5. var Circle = require('./nodes/shapes/Circle').default;
  6. var CircularImage = require('./nodes/shapes/CircularImage').default;
  7. var Database = require('./nodes/shapes/Database').default;
  8. var Diamond = require('./nodes/shapes/Diamond').default;
  9. var Dot = require('./nodes/shapes/Dot').default;
  10. var Ellipse = require('./nodes/shapes/Ellipse').default;
  11. var Icon = require('./nodes/shapes/Icon').default;
  12. var Image = require('./nodes/shapes/Image').default;
  13. var Square = require('./nodes/shapes/Square').default;
  14. var Hexagon = require('./nodes/shapes/Hexagon').default;
  15. var Star = require('./nodes/shapes/Star').default;
  16. var Text = require('./nodes/shapes/Text').default;
  17. var Triangle = require('./nodes/shapes/Triangle').default;
  18. var TriangleDown = require('./nodes/shapes/TriangleDown').default;
  19. var { printStyle } = require("../../../shared/Validator");
  20. /**
  21. * A node. A node can be connected to other nodes via one or multiple edges.
  22. */
  23. class Node {
  24. /**
  25. *
  26. * @param {object} options An object containing options for the node. All
  27. * options are optional, except for the id.
  28. * {number} id Id of the node. Required
  29. * {string} label Text label for the node
  30. * {number} x Horizontal position of the node
  31. * {number} y Vertical position of the node
  32. * {string} shape Node shape
  33. * {string} image An image url
  34. * {string} title A title text, can be HTML
  35. * {anytype} group A group name or number
  36. *
  37. * @param {Object} body Shared state of current network instance
  38. * @param {Network.Images} imagelist A list with images. Only needed when the node has an image
  39. * @param {Groups} grouplist A list with groups. Needed for retrieving group options
  40. * @param {Object} globalOptions Current global node options; these serve as defaults for the node instance
  41. * @param {Object} defaultOptions Global default options for nodes; note that this is also the prototype
  42. * for parameter `globalOptions`.
  43. */
  44. constructor(options, body, imagelist, grouplist, globalOptions, defaultOptions) {
  45. this.options = util.bridgeObject(globalOptions);
  46. this.globalOptions = globalOptions;
  47. this.defaultOptions = defaultOptions;
  48. this.body = body;
  49. this.edges = []; // all edges connected to this node
  50. // set defaults for the options
  51. this.id = undefined;
  52. this.imagelist = imagelist;
  53. this.grouplist = grouplist;
  54. // state options
  55. this.x = undefined;
  56. this.y = undefined;
  57. this.baseSize = this.options.size;
  58. this.baseFontSize = this.options.font.size;
  59. this.predefinedPosition = false; // used to check if initial fit should just take the range or approximate
  60. this.selected = false;
  61. this.hover = false;
  62. this.labelModule = new Label(this.body, this.options, false /* Not edge label */);
  63. this.setOptions(options);
  64. }
  65. /**
  66. * Attach a edge to the node
  67. * @param {Edge} edge
  68. */
  69. attachEdge(edge) {
  70. if (this.edges.indexOf(edge) === -1) {
  71. this.edges.push(edge);
  72. }
  73. }
  74. /**
  75. * Detach a edge from the node
  76. *
  77. * @param {Edge} edge
  78. */
  79. detachEdge(edge) {
  80. var index = this.edges.indexOf(edge);
  81. if (index != -1) {
  82. this.edges.splice(index, 1);
  83. }
  84. }
  85. /**
  86. * Set or overwrite options for the node
  87. *
  88. * @param {Object} options an object with options
  89. * @returns {null|boolean}
  90. */
  91. setOptions(options) {
  92. let currentShape = this.options.shape;
  93. if (!options) {
  94. return; // Note that the return value will be 'undefined'! This is OK.
  95. }
  96. // basic options
  97. if (options.id !== undefined) {this.id = options.id;}
  98. if (this.id === undefined) {
  99. throw new Error("Node must have an id");
  100. }
  101. Node.checkMass(options, this.id);
  102. // set these options locally
  103. // clear x and y positions
  104. if (options.x !== undefined) {
  105. if (options.x === null) {this.x = undefined; this.predefinedPosition = false;}
  106. else {this.x = parseInt(options.x); this.predefinedPosition = true;}
  107. }
  108. if (options.y !== undefined) {
  109. if (options.y === null) {this.y = undefined; this.predefinedPosition = false;}
  110. else {this.y = parseInt(options.y); this.predefinedPosition = true;}
  111. }
  112. if (options.size !== undefined) {this.baseSize = options.size;}
  113. if (options.value !== undefined) {options.value = parseFloat(options.value);}
  114. // this transforms all shorthands into fully defined options
  115. Node.parseOptions(this.options, options, true, this.globalOptions, this.grouplist);
  116. let pile = [options, this.options, this.defaultOptions];
  117. this.chooser = ComponentUtil.choosify('node', pile);
  118. this._load_images();
  119. this.updateLabelModule(options);
  120. this.updateShape(currentShape);
  121. return (options.hidden !== undefined || options.physics !== undefined);
  122. }
  123. /**
  124. * Load the images from the options, for the nodes that need them.
  125. *
  126. * Images are always loaded, even if they are not used in the current shape.
  127. * The user may switch to an image shape later on.
  128. *
  129. * @private
  130. */
  131. _load_images() {
  132. if (this.options.shape === 'circularImage' || this.options.shape === 'image') {
  133. if (this.options.image === undefined) {
  134. throw new Error("Option image must be defined for node type '" + this.options.shape + "'");
  135. }
  136. }
  137. if (this.options.image === undefined) {
  138. return;
  139. }
  140. if (this.imagelist === undefined) {
  141. throw new Error("Internal Error: No images provided");
  142. }
  143. if (typeof this.options.image === 'string') {
  144. this.imageObj = this.imagelist.load(this.options.image, this.options.brokenImage, this.id);
  145. } else {
  146. if (this.options.image.unselected === undefined) {
  147. throw new Error("No unselected image provided");
  148. }
  149. this.imageObj = this.imagelist.load(this.options.image.unselected, this.options.brokenImage, this.id);
  150. if (this.options.image.selected !== undefined) {
  151. this.imageObjAlt = this.imagelist.load(this.options.image.selected, this.options.brokenImage, this.id);
  152. } else {
  153. this.imageObjAlt = undefined;
  154. }
  155. }
  156. }
  157. /**
  158. * Copy group option values into the node options.
  159. *
  160. * The group options override the global node options, so the copy of group options
  161. * must happen *after* the global node options have been set.
  162. *
  163. * This method must also be called also if the global node options have changed and the group options did not.
  164. *
  165. * @param {Object} parentOptions
  166. * @param {Object} newOptions new values for the options, currently only passed in for check
  167. * @param {Object} groupList
  168. */
  169. static updateGroupOptions(parentOptions, newOptions, groupList) {
  170. if (groupList === undefined) return; // No groups, nothing to do
  171. var group = parentOptions.group;
  172. // paranoia: the selected group is already merged into node options, check.
  173. if (newOptions !== undefined && newOptions.group !== undefined && group !== newOptions.group) {
  174. throw new Error("updateGroupOptions: group values in options don't match.");
  175. }
  176. var hasGroup = (typeof group === 'number' || (typeof group === 'string' && group != ''));
  177. if (!hasGroup) return; // current node has no group, no need to merge
  178. var groupObj = groupList.get(group);
  179. // Skip merging of group font options into parent; these are required to be distinct for labels
  180. // Also skip mergin of color IF it is already defined in the node itself. This is to avoid the color of the
  181. // group overriding the color set at the node level
  182. // TODO: It might not be a good idea either to merge the rest of the options, investigate this.
  183. var skipProperties = ['font'];
  184. if (newOptions !== undefined && newOptions.color !== undefined && newOptions.color != null) skipProperties.push('color');
  185. util.selectiveNotDeepExtend(skipProperties, parentOptions, groupObj);
  186. // the color object needs to be completely defined.
  187. // Since groups can partially overwrite the colors, we parse it again, just in case.
  188. parentOptions.color = util.parseColor(parentOptions.color);
  189. }
  190. /**
  191. * This process all possible shorthands in the new options and makes sure that the parentOptions are fully defined.
  192. * Static so it can also be used by the handler.
  193. *
  194. * @param {Object} parentOptions
  195. * @param {Object} newOptions
  196. * @param {boolean} [allowDeletion=false]
  197. * @param {Object} [globalOptions={}]
  198. * @param {Object} [groupList]
  199. * @static
  200. */
  201. static parseOptions(parentOptions, newOptions, allowDeletion = false, globalOptions = {}, groupList) {
  202. var fields = [
  203. 'color',
  204. 'fixed',
  205. 'shadow'
  206. ];
  207. util.selectiveNotDeepExtend(fields, parentOptions, newOptions, allowDeletion);
  208. Node.checkMass(newOptions);
  209. // merge the shadow options into the parent.
  210. util.mergeOptions(parentOptions, newOptions, 'shadow', globalOptions);
  211. // individual shape newOptions
  212. if (newOptions.color !== undefined && newOptions.color !== null) {
  213. let parsedColor = util.parseColor(newOptions.color);
  214. util.fillIfDefined(parentOptions.color, parsedColor);
  215. }
  216. else if (allowDeletion === true && newOptions.color === null) {
  217. parentOptions.color = util.bridgeObject(globalOptions.color); // set the object back to the global options
  218. }
  219. // handle the fixed options
  220. if (newOptions.fixed !== undefined && newOptions.fixed !== null) {
  221. if (typeof newOptions.fixed === 'boolean') {
  222. parentOptions.fixed.x = newOptions.fixed;
  223. parentOptions.fixed.y = newOptions.fixed;
  224. }
  225. else {
  226. if (newOptions.fixed.x !== undefined && typeof newOptions.fixed.x === 'boolean') {
  227. parentOptions.fixed.x = newOptions.fixed.x;
  228. }
  229. if (newOptions.fixed.y !== undefined && typeof newOptions.fixed.y === 'boolean') {
  230. parentOptions.fixed.y = newOptions.fixed.y;
  231. }
  232. }
  233. }
  234. if (allowDeletion === true && newOptions.font === null) {
  235. parentOptions.font = util.bridgeObject(globalOptions.font); // set the object back to the global options
  236. }
  237. Node.updateGroupOptions(parentOptions, newOptions, groupList);
  238. // handle the scaling options, specifically the label part
  239. if (newOptions.scaling !== undefined) {
  240. util.mergeOptions(parentOptions.scaling, newOptions.scaling, 'label', globalOptions.scaling);
  241. }
  242. }
  243. /**
  244. *
  245. * @returns {{color: *, borderWidth: *, borderColor: *, size: *, borderDashes: (boolean|Array|allOptions.nodes.shapeProperties.borderDashes|{boolean, array}), borderRadius: (number|allOptions.nodes.shapeProperties.borderRadius|{number}|Array), shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *}}
  246. */
  247. getFormattingValues() {
  248. let values = {
  249. color: this.options.color.background,
  250. borderWidth: this.options.borderWidth,
  251. borderColor: this.options.color.border,
  252. size: this.options.size,
  253. borderDashes: this.options.shapeProperties.borderDashes,
  254. borderRadius: this.options.shapeProperties.borderRadius,
  255. shadow: this.options.shadow.enabled,
  256. shadowColor: this.options.shadow.color,
  257. shadowSize: this.options.shadow.size,
  258. shadowX: this.options.shadow.x,
  259. shadowY: this.options.shadow.y
  260. };
  261. if (this.selected || this.hover) {
  262. if (this.chooser === true) {
  263. if (this.selected) {
  264. values.borderWidth *= 2;
  265. values.color = this.options.color.highlight.background;
  266. values.borderColor = this.options.color.highlight.border;
  267. values.shadow = this.options.shadow.enabled;
  268. } else if (this.hover) {
  269. values.color = this.options.color.hover.background;
  270. values.borderColor = this.options.color.hover.border;
  271. values.shadow = this.options.shadow.enabled;
  272. }
  273. } else if (typeof this.chooser === 'function') {
  274. this.chooser(values, this.options.id, this.selected, this.hover);
  275. if (values.shadow === false) {
  276. if ((values.shadowColor !== this.options.shadow.color) ||
  277. (values.shadowSize !== this.options.shadow.size) ||
  278. (values.shadowX !== this.options.shadow.x) ||
  279. (values.shadowY !== this.options.shadow.y)) {
  280. values.shadow = true;
  281. }
  282. }
  283. }
  284. } else {
  285. values.shadow = this.options.shadow.enabled;
  286. }
  287. return values;
  288. }
  289. /**
  290. *
  291. * @param {Object} options
  292. */
  293. updateLabelModule(options) {
  294. if (this.options.label === undefined || this.options.label === null) {
  295. this.options.label = '';
  296. }
  297. Node.updateGroupOptions(this.options, options, this.grouplist);
  298. //
  299. // Note:The prototype chain for this.options is:
  300. //
  301. // this.options -> NodesHandler.options -> NodesHandler.defaultOptions
  302. // (also: this.globalOptions)
  303. //
  304. // Note that the prototypes are mentioned explicitly in the pile list below;
  305. // WE DON'T WANT THE ORDER OF THE PROTOTYPES!!!! At least, not for font handling of labels.
  306. // This is a good indication that the prototype usage of options is deficient.
  307. //
  308. var currentGroup = this.grouplist.get(this.options.group, false);
  309. let pile = [
  310. options, // new options
  311. this.options, // current node options, see comment above for prototype
  312. currentGroup, // group options, if any
  313. this.globalOptions, // Currently set global node options
  314. this.defaultOptions // Default global node options
  315. ];
  316. this.labelModule.update(this.options, pile);
  317. if (this.labelModule.baseSize !== undefined) {
  318. this.baseFontSize = this.labelModule.baseSize;
  319. }
  320. }
  321. /**
  322. *
  323. * @param {string} currentShape
  324. */
  325. updateShape(currentShape) {
  326. if (currentShape === this.options.shape && this.shape) {
  327. this.shape.setOptions(this.options, this.imageObj, this.imageObjAlt);
  328. }
  329. else {
  330. // choose draw method depending on the shape
  331. switch (this.options.shape) {
  332. case 'box':
  333. this.shape = new Box(this.options, this.body, this.labelModule);
  334. break;
  335. case 'circle':
  336. this.shape = new Circle(this.options, this.body, this.labelModule);
  337. break;
  338. case 'circularImage':
  339. this.shape = new CircularImage(this.options, this.body, this.labelModule, this.imageObj, this.imageObjAlt);
  340. break;
  341. case 'database':
  342. this.shape = new Database(this.options, this.body, this.labelModule);
  343. break;
  344. case 'diamond':
  345. this.shape = new Diamond(this.options, this.body, this.labelModule);
  346. break;
  347. case 'dot':
  348. this.shape = new Dot(this.options, this.body, this.labelModule);
  349. break;
  350. case 'ellipse':
  351. this.shape = new Ellipse(this.options, this.body, this.labelModule);
  352. break;
  353. case 'icon':
  354. this.shape = new Icon(this.options, this.body, this.labelModule);
  355. break;
  356. case 'image':
  357. this.shape = new Image(this.options, this.body, this.labelModule, this.imageObj, this.imageObjAlt);
  358. break;
  359. case 'square':
  360. this.shape = new Square(this.options, this.body, this.labelModule);
  361. break;
  362. case 'hexagon':
  363. this.shape = new Hexagon(this.options, this.body, this.labelModule);
  364. break;
  365. case 'star':
  366. this.shape = new Star(this.options, this.body, this.labelModule);
  367. break;
  368. case 'text':
  369. this.shape = new Text(this.options, this.body, this.labelModule);
  370. break;
  371. case 'triangle':
  372. this.shape = new Triangle(this.options, this.body, this.labelModule);
  373. break;
  374. case 'triangleDown':
  375. this.shape = new TriangleDown(this.options, this.body, this.labelModule);
  376. break;
  377. default:
  378. this.shape = new Ellipse(this.options, this.body, this.labelModule);
  379. break;
  380. }
  381. }
  382. this.needsRefresh();
  383. }
  384. /**
  385. * select this node
  386. */
  387. select() {
  388. this.selected = true;
  389. this.needsRefresh();
  390. }
  391. /**
  392. * unselect this node
  393. */
  394. unselect() {
  395. this.selected = false;
  396. this.needsRefresh();
  397. }
  398. /**
  399. * Reset the calculated size of the node, forces it to recalculate its size
  400. */
  401. needsRefresh() {
  402. this.shape.refreshNeeded = true;
  403. }
  404. /**
  405. * get the title of this node.
  406. * @return {string} title The title of the node, or undefined when no title
  407. * has been set.
  408. */
  409. getTitle() {
  410. return this.options.title;
  411. }
  412. /**
  413. * Calculate the distance to the border of the Node
  414. * @param {CanvasRenderingContext2D} ctx
  415. * @param {number} angle Angle in radians
  416. * @returns {number} distance Distance to the border in pixels
  417. */
  418. distanceToBorder(ctx, angle) {
  419. return this.shape.distanceToBorder(ctx,angle);
  420. }
  421. /**
  422. * Check if this node has a fixed x and y position
  423. * @return {boolean} true if fixed, false if not
  424. */
  425. isFixed() {
  426. return (this.options.fixed.x && this.options.fixed.y);
  427. }
  428. /**
  429. * check if this node is selecte
  430. * @return {boolean} selected True if node is selected, else false
  431. */
  432. isSelected() {
  433. return this.selected;
  434. }
  435. /**
  436. * Retrieve the value of the node. Can be undefined
  437. * @return {number} value
  438. */
  439. getValue() {
  440. return this.options.value;
  441. }
  442. /**
  443. * Get the current dimensions of the label
  444. *
  445. * @return {rect}
  446. */
  447. getLabelSize() {
  448. return this.labelModule.size();
  449. }
  450. /**
  451. * Adjust the value range of the node. The node will adjust it's size
  452. * based on its value.
  453. * @param {number} min
  454. * @param {number} max
  455. * @param {number} total
  456. */
  457. setValueRange(min, max, total) {
  458. if (this.options.value !== undefined) {
  459. var scale = this.options.scaling.customScalingFunction(min, max, total, this.options.value);
  460. var sizeDiff = this.options.scaling.max - this.options.scaling.min;
  461. if (this.options.scaling.label.enabled === true) {
  462. var fontDiff = this.options.scaling.label.max - this.options.scaling.label.min;
  463. this.options.font.size = this.options.scaling.label.min + scale * fontDiff;
  464. }
  465. this.options.size = this.options.scaling.min + scale * sizeDiff;
  466. }
  467. else {
  468. this.options.size = this.baseSize;
  469. this.options.font.size = this.baseFontSize;
  470. }
  471. this.updateLabelModule();
  472. }
  473. /**
  474. * Draw this node in the given canvas
  475. * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
  476. * @param {CanvasRenderingContext2D} ctx
  477. */
  478. draw(ctx) {
  479. let values = this.getFormattingValues();
  480. this.shape.draw(ctx, this.x, this.y, this.selected, this.hover, values);
  481. }
  482. /**
  483. * Update the bounding box of the shape
  484. * @param {CanvasRenderingContext2D} ctx
  485. */
  486. updateBoundingBox(ctx) {
  487. this.shape.updateBoundingBox(this.x,this.y,ctx);
  488. }
  489. /**
  490. * Recalculate the size of this node in the given canvas
  491. * The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d");
  492. * @param {CanvasRenderingContext2D} ctx
  493. */
  494. resize(ctx) {
  495. let values = this.getFormattingValues();
  496. this.shape.resize(ctx, this.selected, this.hover, values);
  497. }
  498. /**
  499. * Determine all visual elements of this node instance, in which the given
  500. * point falls within the bounding shape.
  501. *
  502. * @param {point} point
  503. * @returns {Array.<nodeClickItem|nodeLabelClickItem>} list with the items which are on the point
  504. */
  505. getItemsOnPoint(point) {
  506. var ret = [];
  507. if (this.labelModule.visible()) {
  508. if (ComponentUtil.pointInRect(this.labelModule.getSize(), point)) {
  509. ret.push({nodeId:this.id, labelId:0});
  510. }
  511. }
  512. if (ComponentUtil.pointInRect(this.shape.boundingBox, point)) {
  513. ret.push({nodeId:this.id});
  514. }
  515. return ret;
  516. }
  517. /**
  518. * Check if this object is overlapping with the provided object
  519. * @param {Object} obj an object with parameters left, top, right, bottom
  520. * @return {boolean} True if location is located on node
  521. */
  522. isOverlappingWith(obj) {
  523. return (
  524. this.shape.left < obj.right &&
  525. this.shape.left + this.shape.width > obj.left &&
  526. this.shape.top < obj.bottom &&
  527. this.shape.top + this.shape.height > obj.top
  528. );
  529. }
  530. /**
  531. * Check if this object is overlapping with the provided object
  532. * @param {Object} obj an object with parameters left, top, right, bottom
  533. * @return {boolean} True if location is located on node
  534. */
  535. isBoundingBoxOverlappingWith(obj) {
  536. return (
  537. this.shape.boundingBox.left < obj.right &&
  538. this.shape.boundingBox.right > obj.left &&
  539. this.shape.boundingBox.top < obj.bottom &&
  540. this.shape.boundingBox.bottom > obj.top
  541. );
  542. }
  543. /**
  544. * Check valid values for mass
  545. *
  546. * The mass may not be negative or zero. If it is, reset to 1
  547. *
  548. * @param {object} options
  549. * @param {Node.id} id
  550. * @static
  551. */
  552. static checkMass(options, id) {
  553. if (options.mass !== undefined && options.mass <= 0) {
  554. let strId = '';
  555. if (id !== undefined) {
  556. strId = ' in node id: ' + id;
  557. }
  558. console.log('%cNegative or zero mass disallowed' + strId +
  559. ', setting mass to 1.' , printStyle);
  560. options.mass = 1;
  561. }
  562. }
  563. }
  564. export default Node;