/** * 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; } }; });