| Current Path : /proc/thread-self/cwd/static/frontend/Magento/luma/it_IT/Magento_Ui/js/form/element/ |
| Current File : //proc/thread-self/cwd/static/frontend/Magento/luma/it_IT/Magento_Ui/js/form/element/ui-select.js |
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* @api
*/
define([
'underscore',
'./abstract',
'Magento_Ui/js/lib/key-codes',
'mage/translate',
'ko',
'jquery',
'Magento_Ui/js/lib/view/utils/async'
], function (_, Abstract, keyCodes, $t, ko, $) {
'use strict';
var isTouchDevice = typeof document.ontouchstart !== 'undefined';
/**
* Processing options list
*
* @param {Array} array - Property array
* @param {String} separator - Level separator
* @param {Array} created - list to add new options
*
* @return {Array} Plain options list
*/
function flattenCollection(array, separator, created) {
var i = 0,
length,
childCollection;
array = _.compact(array);
length = array.length;
created = created || [];
for (i; i < length; i++) {
created.push(array[i]);
if (array[i].hasOwnProperty(separator)) {
childCollection = array[i][separator];
delete array[i][separator];
flattenCollection.call(this, childCollection, separator, created);
}
}
return created;
}
/**
* Set levels to options list
*
* @param {Array} array - Property array
* @param {String} separator - Level separator
* @param {Number} level - Starting level
* @param {String} path - path to root
*
* @returns {Array} Array with levels
*/
function setProperty(array, separator, level, path) {
var i = 0,
length,
nextLevel,
nextPath;
array = _.compact(array);
length = array.length;
level = level || 0;
path = path || '';
for (i; i < length; i++) {
if (array[i]) {
_.extend(array[i], {
level: level,
path: path
});
}
if (array[i].hasOwnProperty(separator)) {
nextLevel = level + 1;
nextPath = path ? path + '.' + array[i].label : array[i].label;
setProperty.call(this, array[i][separator], separator, nextLevel, nextPath);
}
}
return array;
}
/**
* Preprocessing options list
*
* @param {Array} nodes - Options list
*
* @return {Object} Object with property - options(options list)
* and cache options with plain and tree list
*/
function parseOptions(nodes) {
var caption,
value,
cacheNodes,
copyNodes;
nodes = setProperty(nodes, 'optgroup');
copyNodes = JSON.parse(JSON.stringify(nodes));
cacheNodes = flattenCollection(copyNodes, 'optgroup');
nodes = _.map(nodes, function (node) {
value = node.value;
if (value == null || value === '') {
if (_.isUndefined(caption)) {
caption = node.label;
}
} else {
return node;
}
});
return {
options: _.compact(nodes),
cacheOptions: {
plain: _.compact(cacheNodes),
tree: _.compact(nodes)
}
};
}
return Abstract.extend({
defaults: {
options: [],
total: 0,
listVisible: false,
value: [],
filterOptions: false,
chipsEnabled: true,
itemsQuantity: '',
filterInputValue: '',
filterOptionsFocus: false,
multiselectFocus: false,
multiple: true,
selectType: 'tree',
lastSelectable: false,
showFilteredQuantity: true,
showCheckbox: true,
levelsVisibility: true,
openLevelsAction: true,
showOpenLevelsActionIcon: true,
optgroupLabels: false,
closeBtn: true,
showPath: true,
labelsDecoration: false,
disableLabel: false,
filterRateLimit: 500,
filterRateLimitMethod: 'notifyAtFixedRate',
closeBtnLabel: $t('Done'),
optgroupTmpl: 'ui/grid/filters/elements/ui-select-optgroup',
quantityPlaceholder: $t('options'),
hoverClass: '_hover',
rootListSelector: 'ul.admin__action-multiselect-menu-inner._root',
visibleOptionSelector: 'li.admin__action-multiselect-menu-inner-item:visible',
actionTargetSelector: '.action-menu-item',
selectedPlaceholders: {
defaultPlaceholder: $t('Select...'),
lotPlaceholders: $t('Selected')
},
separator: 'optgroup',
searchOptions: false,
loading: false,
searchUrl: false,
lastSearchKey: '',
lastSearchPage: 1,
filterPlaceholder: '',
emptyOptionsHtml: '',
cachedSearchResults: {},
pageLimit: 50,
deviation: 30,
validationLoading: false,
isRemoveSelectedIcon: false,
debounce: 300,
missingValuePlaceholder: $t('Entity with ID: %s doesn\'t exist'),
isDisplayMissingValuePlaceholder: false,
currentSearchKey: '',
listens: {
listVisible: 'cleanHoveredElement',
filterInputValue: 'filterOptionsList',
options: 'checkOptionsList'
},
presets: {
single: {
showCheckbox: false,
chipsEnabled: false,
closeBtn: false
},
optgroup: {
showCheckbox: false,
lastSelectable: true,
optgroupLabels: true,
openLevelsAction: false,
labelsDecoration: true,
showOpenLevelsActionIcon: false
}
}
},
/**
* Initializes UISelect component.
*
* @returns {UISelect} Chainable.
*/
initialize: function () {
this._super();
$.async(
this.rootListSelector,
this,
this.onRootListRender.bind(this)
);
return this;
},
/**
* Parses options and merges the result with instance
* Set defaults according to mode and levels configuration
*
* @param {Object} config
* @returns {Object} Chainable.
*/
initConfig: function (config) {
var result = parseOptions(config.options),
defaults = this.constructor.defaults,
multiple = _.isBoolean(config.multiple) ? config.multiple : defaults.multiple,
type = config.selectType || defaults.selectType,
showOpenLevelsActionIcon = _.isBoolean(config.showOpenLevelsActionIcon) ?
config.showOpenLevelsActionIcon :
defaults.showOpenLevelsActionIcon,
openLevelsAction = _.isBoolean(config.openLevelsAction) ?
config.openLevelsAction :
defaults.openLevelsAction;
multiple = !multiple ? 'single' : false;
config.showOpenLevelsActionIcon = showOpenLevelsActionIcon && openLevelsAction;
_.extend(config, result, defaults.presets[multiple], defaults.presets[type]);
this._super();
return this;
},
/**
* Check child optgroup
*/
hasChildList: function () {
return _.find(this.options(), function (option) {
return !!option[this.separator];
}, this);
},
/**
* Check tree mode
*/
isTree: function () {
return this.hasChildList() && this.selectType !== 'optgroup';
},
/**
* Add option to lastOptions array
*
* @param {Object} data
* @returns {Boolean}
*/
addLastElement: function (data) {
if (!data.hasOwnProperty(this.separator)) {
!this.cacheOptions.lastOptions ? this.cacheOptions.lastOptions = [] : false;
if (!_.findWhere(
this.cacheOptions.lastOptions,
{
value: data.value
}
)
) {
this.cacheOptions.lastOptions.push(data);
}
return true;
}
return false;
},
/**
* Return empty options html
*/
getEmptyOptionsUnsanitizedHtml: function () {
return this.emptyOptionsHtml;
},
/**
* Check options length and set to cache
* if some options is added
*
* @param {Array} options - ui select options
*/
checkOptionsList: function (options) {
if (options.length > this.cacheOptions.plain.length) {
this.cacheOptions.plain = options;
this.setCaption();
}
},
/**
* Check label decoration
*/
isLabelDecoration: function (data) {
return data.hasOwnProperty(this.separator) && this.labelsDecoration;
},
/**
* Calls 'initObservable' of parent, initializes 'options' and 'initialOptions'
* properties, calls 'setOptions' passing options to it
*
* @returns {Object} Chainable.
*/
initObservable: function () {
this._super();
this.observe([
'listVisible',
'placeholder',
'multiselectFocus',
'options',
'itemsQuantity',
'filterInputValue',
'filterOptionsFocus',
'loading',
'validationLoading',
'isDisplayMissingValuePlaceholder'
]);
this.filterInputValue.extend({
rateLimit: {
timeout: this.filterRateLimit,
method: this.filterRateLimitMethod
}
});
return this;
},
/**
* object with key - keyname and value - handler function for this key
*
* @returns {Object} Object with handlers function name.
*/
keyDownHandlers: function () {
return {
enterKey: this.enterKeyHandler,
escapeKey: this.escapeKeyHandler,
spaceKey: this.enterKeyHandler,
pageUpKey: this.pageUpKeyHandler,
pageDownKey: this.pageDownKeyHandler
};
},
/**
* Processing level visibility for levels
*
* @param {Object} data - element data
*
* @returns {Boolean} level visibility.
*/
showLevels: function (data) {
var curLevel = ++data.level,
isVisible;
if (data.visible) {
isVisible = data.visible();
} else {
isVisible = !!data.hasOwnProperty(this.separator) &&
_.isBoolean(this.levelsVisibility) &&
this.levelsVisibility ||
data.hasOwnProperty(this.separator) && parseInt(this.levelsVisibility, 10) >= curLevel;
data.visible = ko.observable(isVisible);
data.isVisited = isVisible;
}
return isVisible;
},
/**
* Processing level visibility for levels
*
* @param {Object} data - element data
*
* @returns {Boolean} level visibility.
*/
getLevelVisibility: function (data) {
if (data.visible) {
return data.visible();
}
return this.showLevels(data);
},
/**
* Set option to options array.
*
* @param {Object} option
* @param {Array} options
*/
setOption: function (option, options) {
var copyOptionsTree;
options = options || this.cacheOptions.tree;
_.each(options, function (opt) {
if (opt.value == option.parent) { //eslint-disable-line eqeqeq
delete option.parent;
opt[this.separator] ? opt[this.separator].push(option) : opt[this.separator] = [option];
copyOptionsTree = JSON.parse(JSON.stringify(this.cacheOptions.tree));
this.cacheOptions.plain = flattenCollection(copyOptionsTree, this.separator);
this.options(this.cacheOptions.tree);
} else if (opt[this.separator]) {
this.setOption(option, opt[this.separator]);
}
}, this);
},
/**
* Handler outerClick event. Closed options list
*/
outerClick: function () {
this.listVisible() ? this.listVisible(false) : false;
if (isTouchDevice) {
this.multiselectFocus(false);
}
},
/**
* Handler keydown event to filter options input
*
* @returns {Boolean} Returned true for emersion events
*/
filterOptionsKeydown: function (data, event) {
var key = keyCodes[event.keyCode];
!this.isTabKey(event) ? event.stopPropagation() : false;
if (key === 'pageDownKey' || key === 'pageUpKey') {
event.preventDefault();
this.filterOptionsFocus(false);
this.cacheUiSelect.focus();
}
this.keydownSwitcher(data, event);
return true;
},
/**
* Filtered options list by value from filter options list
*/
filterOptionsList: function () {
var value = this.filterInputValue().trim().toLowerCase(),
array = [];
if (this.searchOptions) {
return this.loadOptions(value);
}
this.cleanHoveredElement();
if (!value) {
this.renderPath = false;
this.options(this.cacheOptions.tree);
this._setItemsQuantity(false);
return false;
}
this.showPath ? this.renderPath = true : false;
if (this.filterInputValue()) {
array = this.selectType === 'optgroup' ?
this._getFilteredArray(this.cacheOptions.lastOptions, value) :
this._getFilteredArray(this.cacheOptions.plain, value);
if (!value.length) {
this.options(this.cacheOptions.plain);
this._setItemsQuantity(this.cacheOptions.plain.length);
} else {
this.options(array);
this._setItemsQuantity(array.length);
}
return false;
}
this.options(this.cacheOptions.plain);
},
/**
* Filtered options list by value from filter options list
*
* @param {Array} list - option list
* @param {String} value
*
* @returns {Array} filters result
*/
_getFilteredArray: function (list, value) {
var i = 0,
array = [],
curOption;
for (i; i < list.length; i++) {
curOption = list[i].label.toLowerCase();
if (curOption.indexOf(value) > -1) {
array.push(list[i]); /*eslint max-depth: [2, 4]*/
}
}
return array;
},
/**
* Get path to current option
*
* @param {Object} data - option data
* @returns {String} path
*/
getPath: function (data) {
var pathParts,
createdPath = '';
if (this.renderPath) {
pathParts = data.path.split('.');
_.each(pathParts, function (curData) {
createdPath = createdPath ? createdPath + ' / ' + curData : curData;
});
return createdPath;
}
},
/**
* Set filtered items quantity
*
* @param {Object} data - option data
*/
_setItemsQuantity: function (data) {
if (this.showFilteredQuantity) {
data || parseInt(data, 10) === 0 ?
this.itemsQuantity(this.getItemsPlaceholder(data)) :
this.itemsQuantity('');
}
},
/**
* Return formatted items placeholder.
*
* @param {Object} data - option data
* @returns {String}
*/
getItemsPlaceholder: function (data) {
return data + ' ' + this.quantityPlaceholder;
},
/**
* Remove element from selected array
*/
removeSelected: function (value, data, event) {
event ? event.stopPropagation() : false;
this.value.remove(value);
},
/**
* Checked key name
*
* @returns {Boolean}
*/
isTabKey: function (event) {
return keyCodes[event.keyCode] === 'tabKey';
},
/**
* Clean hoveredElement variable
*
* @returns {Object} Chainable
*/
cleanHoveredElement: function () {
if (this.hoveredElement) {
$(this.hoveredElement)
.children(this.actionTargetSelector)
.removeClass(this.hoverClass);
this.hoveredElement = null;
}
return this;
},
/**
* Check selected option
*
* @param {String} value - option value
* @return {Boolean}
*/
isSelected: function (value) {
return this.multiple ? _.contains(this.value(), value) : this.value() === value;
},
/**
* Check selected option
*
* @param {Object} option - option value
* @return {Boolean}
*/
isSelectedValue: function (option) {
if (_.isUndefined(option)) {
return false;
}
return this.isSelected(option.value);
},
/**
* Check optgroup label
*
* @param {Object} data - element data
* @return {Boolean}
*/
isOptgroupLabels: function (data) {
return data.hasOwnProperty(this.separator) && this.optgroupLabels;
},
/**
* Check hovered option
*
* @param {Object} data - element data
* @return {Boolean}
*/
isHovered: function (data) {
var element = this.hoveredElement,
elementData;
if (!element) {
return false;
}
elementData = ko.dataFor(this.hoveredElement);
if (_.isUndefined(elementData)) {
return false;
}
return data.value === elementData.value;
},
/**
* Toggle list visibility
*
* @returns {Object} Chainable
*/
toggleListVisible: function () {
this.listVisible(!this.disabled() && !this.listVisible());
return this;
},
/**
* Get selected element labels
*
* @returns {Array} array labels
*/
getSelected: function () {
var selected = this.value();
return this.cacheOptions.plain.filter(function (opt) {
return _.isArray(selected) ?
_.contains(selected, opt.value) :
selected == opt.value;//eslint-disable-line eqeqeq
});
},
/**
* Toggle activity list element
*
* @param {Object} data - selected option data
* @returns {Object} Chainable
*/
toggleOptionSelected: function (data) {
var isSelected = this.isSelected(data.value);
if (this.lastSelectable && data.hasOwnProperty(this.separator)) {
return this;
}
if (!this.multiple) {
if (!isSelected) {
this.value(data.value);
}
this.listVisible(false);
} else {
if (!isSelected) { /*eslint no-lonely-if: 0*/
this.value.push(data.value);
} else {
this.value(_.without(this.value(), data.value));
}
}
return this;
},
/**
* Change visibility to child level
*
* @param {Object} data - element data
*/
openChildLevel: function (data) {
var contextElement = data,
isVisible;
if (
this.openLevelsAction &&
data.hasOwnProperty(this.separator) && _.isBoolean(this.levelsVisibility) ||
this.openLevelsAction &&
data.hasOwnProperty(this.separator) && parseInt(this.levelsVisibility, 10) <= data.level
) {
isVisible = !contextElement.visible();
if (isVisible && !contextElement.isVisited) {
contextElement.isVisited = true;
}
contextElement.visible(isVisible);
}
},
/**
* Check selected elements
*
* @returns {Boolean}
*/
hasData: function () {
if (!this.value()) {
this.value([]);
}
return this.value() ? !!this.value().length : false;
},
/**
* Handles hover on list items.
*
* @param {Object} event - mousemove event
*/
onDelegatedMouseMove: function (event) {
var target = $(event.currentTarget).closest(this.visibleOptionSelector)[0];
if (this.isCursorPositionChange(event) || this.hoveredElement === target) {
return;
}
this._hoverTo(target);
this.setCursorPosition(event);
},
/**
* Get option index
*
* @param {Object} data - object with data about this element
*
* @returns {Number}
*/
getOptionIndex: function (data) {
var index;
_.each(this.cacheOptions.plain, function (opt, id) {
if (data.value === opt.value) {
index = id;
}
});
return index;
},
/**
* Set X and Y cursor position
*
* @param {Object} event - mousemove event
*/
setCursorPosition: function (event) {
this.cursorPosition = {
x: event.pageX,
y: event.pageY
};
},
/**
* Check previous and current cursor position
*
* @param {Object} event - mousemove event
* @returns {Boolean}
*/
isCursorPositionChange: function (event) {
return this.cursorPosition &&
this.cursorPosition.x === event.pageX &&
this.cursorPosition.y === event.pageY;
},
/**
* Set true to observable variable multiselectFocus
* @param {Object} ctx
* @param {Object} event - focus event
*/
onFocusIn: function (ctx, event) {
!this.cacheUiSelect ? this.cacheUiSelect = event.target : false;
this.multiselectFocus(true);
},
/**
* Set false to observable variable multiselectFocus
* and close list
*/
onFocusOut: function () {
this.multiselectFocus(false);
},
/**
* Handler enter key, if select list is closed - open select,
* if select list is open toggle selected current option
*/
enterKeyHandler: function () {
if (this.filterOptionsFocus()) {
return false;
}
if (this.listVisible()) {
if (this.hoveredElement) {
this.toggleOptionSelected(ko.dataFor(this.hoveredElement));
}
} else {
this.setListVisible(true);
}
},
/**
* Handler escape key, if select list is open - closes it,
*/
escapeKeyHandler: function () {
this.listVisible() ? this.setListVisible(false) : false;
},
/**
* Handler pageDown key, selected next option in list, if current option is last
* selected first option in list
*/
pageDownKeyHandler: function () {
this._setHoverToElement(1);
},
/**
* Get jQuery element by option data
*
* @param {Object} data - option data
*
* @returns {Object} jQuery element
*/
_getElemByData: function (data) {
var i = 0,
list = $(this.cacheUiSelect).find('li'),
length = this.options().length,
result;
for (i; i < length; i++) {
if (this.options()[i].value === data.value) {
result = $(list[i]);
}
}
return result;
},
/**
* Set hover to visible element
*
* @param {Number} direction - iterator
*/
_setHoverToElement: function (direction) {
var element;
if (direction === 1) {
element = this._getNextElement();
} else if (direction === -1) {
element = this._getPreviousElement();
}
if (element) {
this._hoverTo(element);
this._scrollTo(element);
}
},
/**
* Find current hovered element
* and change scroll position
*
* @param {Number} element - element index
*/
_scrollTo: function (element) {
var curEl = $(element).children(this.actionTargetSelector),
wrapper = $(this.rootList),
curElPos = {},
wrapperPos = {};
curElPos.start = curEl.offset().top;
curElPos.end = curElPos.start + curEl.outerHeight();
wrapperPos.start = wrapper.offset().top;
wrapperPos.end = wrapperPos.start + wrapper.height();
if (curElPos.start < wrapperPos.start) {
wrapper.scrollTop(wrapper.scrollTop() - (wrapperPos.start - curElPos.start));
} else if (curElPos.end > wrapperPos.end) {
wrapper.scrollTop(wrapper.scrollTop() + curElPos.end - wrapperPos.end);
}
},
/**
* Handler pageUp key, selected previous option in list, if current option is first -
* selected last option in list
*/
pageUpKeyHandler: function () {
this._setHoverToElement(-1);
},
/**
* Switcher to parse keydown event and delegate event to needful method
*
* @param {Object} data - element data
* @param {Object} event - keydown event
* @returns {Boolean} if handler for this event doesn't found return true
*/
keydownSwitcher: function (data, event) {
var keyName = keyCodes[event.keyCode];
if (this.isTabKey(event)) {
if (!this.filterOptionsFocus() && this.listVisible() && this.filterOptions) {
this.cacheUiSelect.trigger('blur');
this.filterOptionsFocus(true);
this.cleanHoveredElement();
return false;
}
this.listVisible(false);
return true;
}
if (this.keyDownHandlers().hasOwnProperty(keyName)) {
this.keyDownHandlers()[keyName].apply(this, arguments);
} else {
return true;
}
},
/**
* Set caption
*/
setCaption: function () {
var length, caption = '';
if (!_.isArray(this.value()) && this.value()) {
length = 1;
} else if (this.value()) {
length = this.value().length;
} else {
this.value([]);
length = 0;
}
this.warn(caption);
//check if option was removed
if (this.isDisplayMissingValuePlaceholder && length && !this.getSelected().length) {
caption = this.missingValuePlaceholder.replace('%s', this.value());
this.placeholder(caption);
this.warn(caption);
return this.placeholder();
}
if (length > 1) {
this.placeholder(length + ' ' + this.selectedPlaceholders.lotPlaceholders);
} else if (length && this.getSelected().length) {
this.placeholder(this.getSelected()[0].label);
} else {
this.placeholder(this.selectedPlaceholders.defaultPlaceholder);
}
return this.placeholder();
},
/**
* Set list status, open or close
*
* @param {Boolean} value - variable for set list visible status
*/
setListVisible: function (value) {
this.listVisible(value);
},
/**
* Processes preview for option by it's value, and sets the result
* to 'preview' observable
*
* @returns {String}
*/
getPreview: function () {
var selected = this.getSelected();
return selected.map(function (option) {
return option.label;
}).join(', ');
},
/**
* Defines previous option element to
* the one that is currently hovered.
*
* @returns {Element}
*/
_getPreviousElement: function () {
var currentElement = this.hoveredElement,
lastElement = this._getLastIn(this.rootList),
previousElement;
if (!currentElement) {
return lastElement;
}
previousElement = $(currentElement).prev()[0];
return this._getLastIn(previousElement) ||
previousElement ||
this._getFirstParentOf(currentElement) ||
lastElement;
},
/**
* Defines next option element to
* the one that is currently hovered.
*
* @returns {Element}
*/
_getNextElement: function () {
var currentElement = this.hoveredElement,
firstElement = this._getFirstIn(this.rootList);
if (!currentElement) {
return firstElement;
}
return this._getFirstIn(currentElement) ||
$(currentElement).next()[0] ||
this._getParentsOf(currentElement).next()[0] ||
firstElement;
},
/**
* Returns first option element in provided scope.
*
* @param {Element} scope
* @returns {Element}
*/
_getFirstIn: function (scope) {
return $(scope).find(this.visibleOptionSelector)[0];
},
/**
* Returns last descendant option element in provided scope.
*
* @param {Element} scope
* @returns {Element}
*/
_getLastIn: function (scope) {
return $(scope).find(this.visibleOptionSelector).last()[0];
},
/**
* Returns a collection of parent option elements.
*
* @param {Element} scope
* @returns {jQueryCollection}
*/
_getParentsOf: function (scope) {
return $(scope).parents(this.visibleOptionSelector);
},
/**
* Returns first parent option element.
*
* @param {Element} scope
* @returns {Element}
*/
_getFirstParentOf: function (scope) {
return this._getParentsOf(scope)[0];
},
/**
* Sets hover class to provided option element.
*
* @param {Element} element
*/
_hoverTo: function (element) {
if (this.hoveredElement) {
$(this.hoveredElement)
.children(this.actionTargetSelector)
.removeClass(this.hoverClass);
}
$(element)
.children(this.actionTargetSelector)
.addClass(this.hoverClass);
this.hoveredElement = element;
},
/**
* Callback which fires when root list element is rendered.
*
* @param {Element} element
*/
onRootListRender: function (element) {
var targetSelector = 'li > ' + this.actionTargetSelector;
this.rootList = element;
$(this.rootList).on(
'mousemove',
targetSelector,
this.onDelegatedMouseMove.bind(this)
);
},
/**
* Returns options from cache or send request
*
* @param {String} searchKey
*/
loadOptions: function (searchKey) {
var currentPage = searchKey === this.lastSearchKey ? this.lastSearchPage + 1 : 1,
cachedSearchResult;
this.renderPath = !!this.showPath;
if (this.isSearchKeyCached(searchKey)) {
cachedSearchResult = this.getCachedSearchResults(searchKey);
this.cacheOptions.plain = cachedSearchResult.options;
this.options(cachedSearchResult.options);
this.afterLoadOptions(searchKey, cachedSearchResult.lastPage, cachedSearchResult.total);
return;
}
if (currentPage === 1) {
this.options([]);
}
this.processRequest(searchKey, currentPage);
},
/**
* Load more options on scroll down
* @param {Object} data
* @param {Event} event
*/
onScrollDown: function (data, event) {
var clientHight = event.target.scrollTop + event.target.clientHeight,
scrollHeight = event.target.scrollHeight;
if (!this.searchOptions) {
return;
}
if (clientHight > scrollHeight - this.deviation && !this.isSearchKeyCached(data.filterInputValue())) {
this.loadOptions(data.filterInputValue());
}
},
/**
* Returns cached search result by search key
*
* @param {String} searchKey
* @return {Object}
*/
getCachedSearchResults: function (searchKey) {
if (this.cachedSearchResults.hasOwnProperty(searchKey)) {
return this.cachedSearchResults[searchKey];
}
return {
options: [],
lastPage: 1,
total: 0
};
},
/**
* Cache loaded data
*
* @param {String} searchKey
* @param {Array} optionsArray
* @param {Number} page
* @param {Number} total
*/
setCachedSearchResults: function (searchKey, optionsArray, page, total) {
var cachedData = {};
cachedData.options = optionsArray;
cachedData.lastPage = page;
cachedData.total = total;
this.cachedSearchResults[searchKey] = cachedData;
},
/**
* Check if search key cached
*
* @param {String} searchKey
* @return {Boolean}
*/
isSearchKeyCached: function (searchKey) {
var totalCached = this.cachedSearchResults.hasOwnProperty(searchKey) ?
this.deviation * this.cachedSearchResults[searchKey].lastPage :
0;
return totalCached > 0 && totalCached >= this.cachedSearchResults[searchKey].total;
},
/**
* Submit request to load data
*
* @param {String} searchKey
* @param {Number} page
*/
processRequest: function (searchKey, page) {
this.loading(true);
this.currentSearchKey = searchKey;
$.ajax({
url: this.searchUrl,
type: 'get',
dataType: 'json',
context: this,
data: {
searchKey: searchKey,
page: page,
limit: this.pageLimit
},
success: $.proxy(this.success, this),
error: $.proxy(this.error, this),
beforeSend: $.proxy(this.beforeSend, this),
complete: $.proxy(this.complete, this, searchKey, page)
});
},
/** @param {Object} response */
success: function (response) {
var existingOptions = this.options();
_.each(response.options, function (opt) {
existingOptions.push(opt);
});
this.total = response.total;
this.cacheOptions.plain = existingOptions;
this.options(existingOptions);
},
/** add actions before ajax request */
beforeSend: function () {
},
/** set empty array if error occurs */
error: function () {
this.options([]);
},
/** cache options and stop loading*/
complete: function (searchKey, page) {
this.setCachedSearchResults(searchKey, this.options(), page, this.total);
this.afterLoadOptions(searchKey, page, this.total);
},
/**
* Stop loading and update data after options were updated
*
* @param {String} searchKey
* @param {Number} page
* @param {Number} total
*/
afterLoadOptions: function (searchKey, page, total) {
this.lastSearchKey = searchKey;
this.lastSearchPage = page;
this._setItemsQuantity(total);
this.loading(false);
}
});
});