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.

112 lines
3.4 KiB

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