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.

109 lines
3.4 KiB

  1. // Utility functions for ordering and stacking of items
  2. /**
  3. * Order items by their start data
  4. * @param {Item[]} items
  5. */
  6. exports.orderByStart = function(items) {
  7. items.sort(function (a, b) {
  8. return a.data.start - b.data.start;
  9. });
  10. };
  11. /**
  12. * Order items by their end date. If they have no end date, their start date
  13. * is used.
  14. * @param {Item[]} items
  15. */
  16. exports.orderByEnd = function(items) {
  17. items.sort(function (a, b) {
  18. var aTime = ('end' in a.data) ? a.data.end : a.data.start,
  19. bTime = ('end' in b.data) ? b.data.end : b.data.start;
  20. return aTime - bTime;
  21. });
  22. };
  23. /**
  24. * Adjust vertical positions of the items such that they don't overlap each
  25. * other.
  26. * @param {Item[]} items
  27. * All visible items
  28. * @param {{item: number, axis: number}} margin
  29. * Margins between items and between items and the axis.
  30. * @param {boolean} [force=false]
  31. * If true, all items will be repositioned. If false (default), only
  32. * items having a top===null will be re-stacked
  33. */
  34. exports.stack = function(items, margin, force) {
  35. var i, iMax;
  36. if (force) {
  37. // reset top position of all items
  38. for (i = 0, iMax = items.length; i < iMax; i++) {
  39. items[i].top = null;
  40. }
  41. }
  42. // calculate new, non-overlapping positions
  43. for (i = 0, iMax = items.length; i < iMax; i++) {
  44. var item = items[i];
  45. if (item.top === null) {
  46. // initialize top position
  47. item.top = margin.axis;
  48. do {
  49. // TODO: optimize checking for overlap. when there is a gap without items,
  50. // you only need to check for items from the next item on, not from zero
  51. var collidingItem = null;
  52. for (var j = 0, jj = items.length; j < jj; j++) {
  53. var other = items[j];
  54. if (other.top !== null && other !== item && exports.collision(item, other, margin.item)) {
  55. collidingItem = other;
  56. break;
  57. }
  58. }
  59. if (collidingItem != null) {
  60. // There is a collision. Reposition the items above the colliding element
  61. item.top = collidingItem.top + collidingItem.height + margin.item;
  62. }
  63. } while (collidingItem);
  64. }
  65. }
  66. };
  67. /**
  68. * Adjust vertical positions of the items without stacking them
  69. * @param {Item[]} items
  70. * All visible items
  71. * @param {{item: number, axis: number}} margin
  72. * Margins between items and between items and the axis.
  73. */
  74. exports.nostack = function(items, margin) {
  75. var i, iMax;
  76. // reset top position of all items
  77. for (i = 0, iMax = items.length; i < iMax; i++) {
  78. items[i].top = margin.axis;
  79. }
  80. };
  81. /**
  82. * Test if the two provided items collide
  83. * The items must have parameters left, width, top, and height.
  84. * @param {Item} a The first item
  85. * @param {Item} b The second item
  86. * @param {Number} margin A minimum required margin.
  87. * If margin is provided, the two items will be
  88. * marked colliding when they overlap or
  89. * when the margin between the two is smaller than
  90. * the requested margin.
  91. * @return {boolean} true if a and b collide, else false
  92. */
  93. exports.collision = function(a, b, margin) {
  94. return ((a.left - margin) < (b.left + b.width) &&
  95. (a.left + a.width + margin) > b.left &&
  96. (a.top - margin) < (b.top + b.height) &&
  97. (a.top + a.height + margin) > b.top);
  98. };