ordered-list.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. class OrderedList {
  2. constructor(items) {
  3. this.isOrdered = false;
  4. this._items = items || [];
  5. }
  6. add(key, item, order) {
  7. this._items.push({
  8. key: key,
  9. item: item,
  10. after: order ? order.after || null : null,
  11. before: order ? order.before || null : null
  12. });
  13. }
  14. get(key, value) {
  15. for (var i = 0; i < this._items.length; i++) {
  16. if (this._items[i].key === key) {
  17. return this._items[i].item;
  18. }
  19. }
  20. return value;
  21. }
  22. has(key) {
  23. return this.get(key) !== undefined;
  24. }
  25. values() {
  26. var values = [];
  27. for (var i = 0; i < this._items.length; i++) {
  28. values.push(this._items[i].item);
  29. }
  30. return values;
  31. }
  32. order(values_only) {
  33. if (!this.isOrdered) {
  34. this._items = this._order(this._items);
  35. this.isOrdered = true;
  36. }
  37. if (values_only || typeof values_only === 'undefined') {
  38. return this.values();
  39. } else {
  40. return this._items;
  41. }
  42. }
  43. orderedValues() {
  44. return this.order(true);
  45. }
  46. _order(unordered) {
  47. // Index of unordered items
  48. var index = [];
  49. unordered.forEach(function (item) {
  50. index.push(item.key);
  51. });
  52. // Ordered items
  53. var ordered = [];
  54. var ordering = [];
  55. // First pass: register items that
  56. // don't specify their order
  57. unordered.forEach(function (item) {
  58. if (!item.after && !item.before) {
  59. ordered.push(item);
  60. ordering.push(item.key);
  61. }
  62. });
  63. // Second pass: register items that
  64. // specify their before to "_end"
  65. unordered.forEach(function (item) {
  66. if (item.before === "_end") {
  67. ordered.push(item);
  68. ordering.push(item.key);
  69. }
  70. });
  71. // Third pass: keep iterating items
  72. // until we hit iterations limit or finish
  73. // ordering list
  74. function insertItem(item) {
  75. var insertAt = -1;
  76. if (ordering.indexOf(item.key) === -1) {
  77. if (item.after) {
  78. insertAt = ordering.indexOf(item.after);
  79. if (insertAt !== -1) {
  80. insertAt += 1;
  81. }
  82. } else if (item.before) {
  83. insertAt = ordering.indexOf(item.before);
  84. }
  85. if (insertAt !== -1) {
  86. ordered.splice(insertAt, 0, item);
  87. ordering.splice(insertAt, 0, item.key);
  88. }
  89. }
  90. }
  91. var iterations = 200;
  92. while (iterations > 0 && index.length !== ordering.length) {
  93. iterations -= 1;
  94. unordered.forEach(insertItem);
  95. }
  96. return ordered;
  97. }
  98. }
  99. export default OrderedList;