ordered-list.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. (function (Misago) {
  2. 'use strict';
  3. Misago.OrderedList = function(items) {
  4. this.isOrdered = false;
  5. this._items = items || [];
  6. this.add = function(key, item, order) {
  7. this._items.push({
  8. key: key,
  9. item: item,
  10. after: Misago.get(order, 'after'),
  11. before: Misago.get(order, 'before')
  12. });
  13. };
  14. this.get = function(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. this.has = function(key) {
  23. return this.get(key) !== undefined;
  24. };
  25. this.values = function() {
  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. this.order = function(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. this._order = function(unordered) {
  44. // Index of unordered items
  45. var index = [];
  46. unordered.forEach(function (item) {
  47. index.push(item.key);
  48. });
  49. // Ordered items
  50. var ordered = [];
  51. var ordering = [];
  52. // First pass: register items that
  53. // don't specify their order
  54. unordered.forEach(function (item) {
  55. if (!item.after && !item.before) {
  56. ordered.push(item);
  57. ordering.push(item.key);
  58. }
  59. });
  60. // Second pass: register items that
  61. // specify their before to "_end"
  62. unordered.forEach(function (item) {
  63. if (item.before === "_end") {
  64. ordered.push(item);
  65. ordering.push(item.key);
  66. }
  67. });
  68. // Third pass: keep iterating items
  69. // until we hit iterations limit or finish
  70. // ordering list
  71. function insertItem(item) {
  72. var insertAt = -1;
  73. if (ordering.indexOf(item.key) === -1) {
  74. if (item.after) {
  75. insertAt = ordering.indexOf(item.after);
  76. if (insertAt !== -1) {
  77. insertAt += 1;
  78. }
  79. } else if (item.before) {
  80. insertAt = ordering.indexOf(item.before);
  81. }
  82. if (insertAt !== -1) {
  83. ordered.splice(insertAt, 0, item);
  84. ordering.splice(insertAt, 0, item.key);
  85. }
  86. }
  87. }
  88. var iterations = 200;
  89. while (iterations > 0 && index.length !== ordering.length) {
  90. iterations -= 1;
  91. unordered.forEach(insertItem);
  92. }
  93. return ordered;
  94. };
  95. };
  96. } (Misago.prototype));