1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'underscore',
'jquery'
], function (_, $) {
'use strict';
var scriptSelector = 'script[type="text/x-magento-init"]',
dataAttr = 'data-mage-init',
virtuals = [];
/**
* Adds components to the virtual list.
*
* @param {Object} components
*/
function addVirtual(components) {
virtuals.push({
el: false,
data: components
});
}
/**
* Merges provided data with a current data
* of a elements' "data-mage-init" attribute.
*
* @param {Object} components - Object with components and theirs configuration.
* @param {HTMLElement} elem - Element whose data should be modified.
*/
function setData(components, elem) {
var data = elem.getAttribute(dataAttr);
data = data ? JSON.parse(data) : {};
_.each(components, function (obj, key) {
if (_.has(obj, 'mixins')) {
data[key] = data[key] || {};
data[key].mixins = data[key].mixins || [];
data[key].mixins = data[key].mixins.concat(obj.mixins);
delete obj.mixins;
}
});
data = $.extend(true, data, components);
data = JSON.stringify(data);
elem.setAttribute(dataAttr, data);
}
/**
* Search for the elements by privded selector and extends theirs data.
*
* @param {Object} components - Object with components and theirs configuration.
* @param {String} selector - Selector for the elements.
*/
function processElems(components, selector) {
var elems,
iterator;
if (selector === '*') {
addVirtual(components);
return;
}
elems = document.querySelectorAll(selector);
iterator = setData.bind(null, components);
_.toArray(elems).forEach(iterator);
}
/**
* Parses content of a provided script node.
* Note: node will be removed from DOM.
*
* @param {HTMLScriptElement} node - Node to be processed.
* @returns {Object}
*/
function getNodeData(node) {
var data = node.textContent;
node.parentNode.removeChild(node);
return JSON.parse(data);
}
/**
* Parses 'script' tags with a custom type attribute and moves it's data
* to a 'data-mage-init' attribute of an element found by provided selector.
* Note: All found script nodes will be removed from DOM.
*
* @returns {Array} An array of components not assigned to the specific element.
*
* @example Sample declaration.
* <script type="text/x-magento-init">
* {
* "body": {
* "path/to/component": {"foo": "bar"}
* }
* }
* </script>
*
* @example Providing data without selector.
* {
* "*": {
* "path/to/component": {"bar": "baz"}
* }
* }
*/
return function () {
var nodes = document.querySelectorAll(scriptSelector);
_.toArray(nodes)
.map(getNodeData)
.forEach(function (item) {
_.each(item, processElems);
});
return virtuals.splice(0, virtuals.length);
};
});