| Current Path : /home/rtorresani/www/pub/static/frontend/Magento/luma/it_IT/Magento_Ui/js/lib/view/utils/ |
| Current File : //home/rtorresani/www/pub/static/frontend/Magento/luma/it_IT/Magento_Ui/js/lib/view/utils/async.js |
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* @api
*/
define([
'ko',
'jquery',
'underscore',
'uiRegistry',
'./dom-observer',
'Magento_Ui/js/lib/knockout/extender/bound-nodes',
'./bindings'
], function (ko, $, _, registry, domObserver, boundedNodes) {
'use strict';
/**
* Checks if provided value is a dom element.
*
* @param {*} node - Value to be checked.
* @returns {Boolean}
*/
function isDomElement(node) {
return typeof node === 'object' && node.tagName && node.nodeType;
}
/**
* Parses provided string and extracts
* component, context and selector data from it.
*
* @param {String} str - String to be processed.
* @returns {Object} Data retrieved from string.
*
* @example Sample format.
* '{{component}}:{{ctx}} -> {{selector}}'
*
* component - Name of component.
* ctx - Selector of the root node upon which component is binded.
* selector - Selector of DOM elements located
* inside of a previously specified context.
*/
function parseSelector(str) {
var data = str.trim().split('->'),
result = {},
componentData;
if (data.length === 1) {
if (!~data[0].indexOf(':')) {
result.selector = data[0];
} else {
componentData = data[0];
}
} else {
componentData = data[0];
result.selector = data[1];
}
if (componentData) {
componentData = componentData.split(':');
result.component = componentData[0];
result.ctx = componentData[1];
}
_.each(result, function (value, key) {
result[key] = value.trim();
});
return result;
}
/**
* Internal method used to normalize argumnets passed
* to 'async' module methods.
*
* @param {(String|Object)} selector
* @param {(HTMLElement|Object|String)} [ctx]
* @returns {Object}
*/
function parseData(selector, ctx) {
var data = {};
if (arguments.length === 2) {
data.selector = selector;
if (isDomElement(ctx)) {
data.ctx = ctx;
} else {
data.component = ctx;
data.ctx = '*';
}
} else {
data = _.isString(selector) ?
parseSelector(selector) :
selector;
}
return data;
}
/**
* Creates promise that will be resolved
* when requested component is registred.
*
* @param {String} name - Name of component.
* @returns {jQueryPromise}
*/
function waitComponent(name) {
var deffer = $.Deferred();
if (_.isString(name)) {
registry.get(name, function (component) {
deffer.resolve(component);
});
} else {
deffer.resolve(name);
}
return deffer.promise();
}
/**
* Creates listener for the nodes binded to provided component.
*
* @param {Object} data - Listener data.
* @param {Object} component - Associated with nodes component.
*/
function setRootListener(data, component) {
boundedNodes.get(component, function (root) {
if (!$(root).is(data.ctx || '*')) {
return;
}
data.selector ?
domObserver.get(data.selector, data.fn, root) :
data.fn(root);
});
}
/*eslint-disable no-unused-vars*/
/**
* Sets listener for the appearance of elements which
* matches specified selector data.
*
* @param {(String|Object)} selector - Valid css selector or a string
* in format acceptable by 'parseSelector' method or an object with
* 'component', 'selector' and 'ctx' properties.
* @param {(HTMLElement|Object|String)} [ctx] - Optional context parameter
* which might be a DOM element, component instance or components' name.
* @param {Function} fn - Callback that will be invoked
* when required DOM element appears.
*
* @example
* Creating listener of the 'span' nodes appearance,
* located inside of 'div' nodes, which are binded to 'cms_page_listing' component:
*
* $.async('cms_page_listing:div -> span', function (node) {});
*
* @example Another syntaxes of the previous example.
* $.async({
* component: 'cms_page_listing',
* ctx: 'div',
* selector: 'span'
* }, function (node) {});
*
* @example Listens for appearance of any child node inside of specified component.
* $.async('> *', 'cms_page_lsiting', function (node) {});
*
* @example Listens for appearance of 'span' nodes inside of specific context.
* $.async('span', document.getElementById('test'), function (node) {});
*/
$.async = function (selector, ctx, fn) {
var args = _.toArray(arguments),
data = parseData.apply(null, _.initial(args));
data.fn = _.last(args);
if (data.component) {
waitComponent(data.component)
.then(setRootListener.bind(null, data));
} else {
domObserver.get(data.selector, data.fn, data.ctx);
}
};
/*eslint-enable no-unused-vars*/
_.extend($.async, {
/*eslint-disable no-unused-vars*/
/**
* Returns collection of elements found by provided selector data.
*
* @param {(String|Object)} selector - See 'async' definition.
* @param {(HTMLElement|Object|String)} [ctx] - See 'async' definition.
* @returns {Array} An array of DOM elements.
*/
get: function (selector, ctx) {
var data = parseData.apply(null, arguments),
component = data.component,
nodes;
if (!component) {
return $(data.selector, data.ctx).toArray();
} else if (_.isString(component)) {
component = registry.get(component);
}
if (!component) {
return [];
}
nodes = boundedNodes.get(component);
nodes = $(nodes).filter(data.ctx).toArray();
return data.selector ?
$(data.selector, nodes).toArray() :
nodes;
},
/*eslint-enable no-unused-vars*/
/**
* Sets removal listener of the specified nodes.
*
* @param {(HTMLElement|Array|ArrayLike)} nodes - Nodes whose removal to track.
* @param {Function} fn - Callback that will be invoked when node is removed.
*/
remove: function (nodes, fn) {
domObserver.remove(nodes, fn);
},
parseSelector: parseSelector
});
return $;
});