/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'underscore',
'./strings'
], function (_, utils) {
'use strict';
/**
* Defines index of an item in a specified container.
*
* @param {*} item - Item whose index should be defined.
* @param {Array} container - Container upon which to perform search.
* @returns {Number}
*/
function getIndex(item, container) {
var index = container.indexOf(item);
if (~index) {
return index;
}
return _.findIndex(container, function (value) {
return value && value.name === item;
});
}
return {
/**
* Facade method to remove/add value from/to array
* without creating a new instance.
*
* @param {Array} arr - Array to be modified.
* @param {*} value - Value to add/remove.
* @param {Boolean} add - Flag that specfies operation.
* @returns {Utils} Chainable.
*/
toggle: function (arr, value, add) {
return add ?
this.add(arr, value) :
this.remove(arr, value);
},
/**
* Removes the incoming value from array in case
* without creating a new instance of it.
*
* @param {Array} arr - Array to be modified.
* @param {*} value - Value to be removed.
* @returns {Utils} Chainable.
*/
remove: function (arr, value) {
var index = arr.indexOf(value);
if (~index) {
arr.splice(index, 1);
}
return this;
},
/**
* Adds the incoming value to array if
* it's not alredy present in there.
*
* @param {Array} arr - Array to be modifed.
* @param {...*} arguments - Values to be added.
* @returns {Utils} Chainable.
*/
add: function (arr) {
var values = _.toArray(arguments).slice(1);
values.forEach(function (value) {
if (!~arr.indexOf(value)) {
arr.push(value);
}
});
return this;
},
/**
* Inserts specified item into container at a specified position.
*
* @param {*} item - Item to be inserted into container.
* @param {Array} container - Container of items.
* @param {*} [position=-1] - Position at which item should be inserted.
* Position can represent:
* - specific index in container
* - item which might already be present in container
* - structure with one of these properties: after, before
* @returns {Boolean|*}
* - true if element has changed its' position
* - false if nothing has changed
* - inserted value if it wasn't present in container
*/
insert: function (item, container, position) {
var currentIndex = getIndex(item, container),
newIndex,
target;
if (typeof position === 'undefined') {
position = -1;
} else if (typeof position === 'string') {
position = isNaN(+position) ? position : +position;
}
newIndex = position;
if (~currentIndex) {
target = container.splice(currentIndex, 1)[0];
if (typeof item === 'string') {
item = target;
}
}
if (typeof position !== 'number') {
target = position.after || position.before || position;
newIndex = getIndex(target, container);
if (~newIndex && (position.after || newIndex >= currentIndex)) {
newIndex++;
}
}
if (newIndex < 0) {
newIndex += container.length + 1;
}
container[newIndex] ?
container.splice(newIndex, 0, item) :
container[newIndex] = item;
return !~currentIndex ? item : currentIndex !== newIndex;
},
/**
* @param {Array} elems
* @param {Number} offset
* @return {Number|*}
*/
formatOffset: function (elems, offset) {
if (utils.isEmpty(offset)) {
offset = -1;
}
offset = +offset;
if (offset < 0) {
offset += elems.length + 1;
}
return offset;
}
};
});
|