arrays.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /**
  2. * Copyright © Magento, Inc. All rights reserved.
  3. * See COPYING.txt for license details.
  4. */
  5. define([
  6. 'underscore',
  7. './strings'
  8. ], function (_, utils) {
  9. 'use strict';
  10. /**
  11. * Defines index of an item in a specified container.
  12. *
  13. * @param {*} item - Item whose index should be defined.
  14. * @param {Array} container - Container upon which to perform search.
  15. * @returns {Number}
  16. */
  17. function getIndex(item, container) {
  18. var index = container.indexOf(item);
  19. if (~index) {
  20. return index;
  21. }
  22. return _.findIndex(container, function (value) {
  23. return value && value.name === item;
  24. });
  25. }
  26. return {
  27. /**
  28. * Facade method to remove/add value from/to array
  29. * without creating a new instance.
  30. *
  31. * @param {Array} arr - Array to be modified.
  32. * @param {*} value - Value to add/remove.
  33. * @param {Boolean} add - Flag that specfies operation.
  34. * @returns {Utils} Chainable.
  35. */
  36. toggle: function (arr, value, add) {
  37. return add ?
  38. this.add(arr, value) :
  39. this.remove(arr, value);
  40. },
  41. /**
  42. * Removes the incoming value from array in case
  43. * without creating a new instance of it.
  44. *
  45. * @param {Array} arr - Array to be modified.
  46. * @param {*} value - Value to be removed.
  47. * @returns {Utils} Chainable.
  48. */
  49. remove: function (arr, value) {
  50. var index = arr.indexOf(value);
  51. if (~index) {
  52. arr.splice(index, 1);
  53. }
  54. return this;
  55. },
  56. /**
  57. * Adds the incoming value to array if
  58. * it's not alredy present in there.
  59. *
  60. * @param {Array} arr - Array to be modifed.
  61. * @param {...*} arguments - Values to be added.
  62. * @returns {Utils} Chainable.
  63. */
  64. add: function (arr) {
  65. var values = _.toArray(arguments).slice(1);
  66. values.forEach(function (value) {
  67. if (!~arr.indexOf(value)) {
  68. arr.push(value);
  69. }
  70. });
  71. return this;
  72. },
  73. /**
  74. * Inserts specified item into container at a specified position.
  75. *
  76. * @param {*} item - Item to be inserted into container.
  77. * @param {Array} container - Container of items.
  78. * @param {*} [position=-1] - Position at which item should be inserted.
  79. * Position can represent:
  80. * - specific index in container
  81. * - item which might already be present in container
  82. * - structure with one of these properties: after, before
  83. * @returns {Boolean|*}
  84. * - true if element has changed its' position
  85. * - false if nothing has changed
  86. * - inserted value if it wasn't present in container
  87. */
  88. insert: function (item, container, position) {
  89. var currentIndex = getIndex(item, container),
  90. newIndex,
  91. target;
  92. if (typeof position === 'undefined') {
  93. position = -1;
  94. } else if (typeof position === 'string') {
  95. position = isNaN(+position) ? position : +position;
  96. }
  97. newIndex = position;
  98. if (~currentIndex) {
  99. target = container.splice(currentIndex, 1)[0];
  100. if (typeof item === 'string') {
  101. item = target;
  102. }
  103. }
  104. if (typeof position !== 'number') {
  105. target = position.after || position.before || position;
  106. newIndex = getIndex(target, container);
  107. if (~newIndex && (position.after || newIndex >= currentIndex)) {
  108. newIndex++;
  109. }
  110. }
  111. if (newIndex < 0) {
  112. newIndex += container.length + 1;
  113. }
  114. container[newIndex] ?
  115. container.splice(newIndex, 0, item) :
  116. container[newIndex] = item;
  117. return !~currentIndex ? item : currentIndex !== newIndex;
  118. },
  119. /**
  120. * @param {Array} elems
  121. * @param {Number} offset
  122. * @return {Number|*}
  123. */
  124. formatOffset: function (elems, offset) {
  125. if (utils.isEmpty(offset)) {
  126. offset = -1;
  127. }
  128. offset = +offset;
  129. if (offset < 0) {
  130. offset += elems.length + 1;
  131. }
  132. return offset;
  133. }
  134. };
  135. });