scripts.js 3.4 KB

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