Skip to content

Commit 08d4d9b

Browse files
committed
Merge branch 'MAGETWO-86673-frontend-rendering' into MAGETWO-87081-video
2 parents a5bb8b1 + 858c4fb commit 08d4d9b

File tree

17 files changed

+848
-155
lines changed

17 files changed

+848
-155
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\PageBuilder\Block;
10+
11+
use Magento\Framework\View\Element\Template;
12+
13+
/**
14+
* Class WidgetInitializer provides configuration for content types widgets need to be loaded on frontend
15+
* @api
16+
*/
17+
class WidgetInitializer extends Template
18+
{
19+
/**
20+
* @var \Magento\Framework\Serialize\Serializer\Json
21+
*/
22+
private $jsonSerializer;
23+
24+
/**
25+
* WidgetInitializer constructor.
26+
* @param Template\Context $context
27+
* @param \Magento\Framework\Serialize\Serializer\Json $jsonEncoder
28+
* @param array $data
29+
*/
30+
public function __construct(
31+
\Magento\Framework\View\Element\Template\Context $context,
32+
\Magento\Framework\Serialize\Serializer\Json $jsonEncoder,
33+
array $data = []
34+
) {
35+
$this->jsonSerializer = $jsonEncoder;
36+
parent::__construct($context, $data);
37+
}
38+
39+
/**
40+
* Returns config for widgets initializer component.
41+
* @return string
42+
* @api
43+
*/
44+
public function getConfig() : string
45+
{
46+
$widgetsConfig = $this->getData('config');
47+
$resultConfig = [];
48+
foreach ($widgetsConfig as $contentTypeName => $config) {
49+
$selector = sprintf('div[data-role="%s"]', $contentTypeName);
50+
foreach ($config as $item) {
51+
if (!isset($item['component'])) {
52+
continue;
53+
}
54+
if (isset($item['appearance'])) {
55+
$selector .= sprintf('[data-appearance="%s"]', $item['appearance']);
56+
}
57+
$componentConfig = isset($item['config']) ? $item['config'] : '{}';
58+
$resultConfig[$selector] = [$item['component'] => $componentConfig];
59+
}
60+
}
61+
return $this->jsonSerializer->serialize($resultConfig);
62+
}
63+
}

app/code/Magento/PageBuilder/docs/content-type-configuration.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,84 @@ The `tag` element allows you to read the tag name of the element and map back to
406406
<tag name="heading_type"/>
407407
```
408408

409+
## Add custom logic to content types
410+
411+
You can customize Page Builder content types by adding your own logic on the frontend.
412+
413+
To add custom logic to content types:
414+
1. [Create a JavaScript widget](#create-a-javascript-widget)
415+
2. [Add XML configuration to load it on the frontend](#add-xml-configuration-to-load-it-on-the-frontend)
416+
417+
### Create a JavaScript widget
418+
419+
Create a JavaScript widget in your module's `/view/frontend/web/js/content-type/{content-type-name}/appearance/{appearance-name}/widget.js` file:
420+
421+
``` javascript
422+
/**
423+
* Copyright © Magento, Inc. All rights reserved.
424+
* See COPYING.txt for license details.
425+
*/
426+
427+
define([
428+
'jquery',
429+
'slick'
430+
], function ($) {
431+
'use strict';
432+
433+
return function (config, sliderElement) {
434+
435+
var $element = $(sliderElement);
436+
437+
/**
438+
* Prevent each slick slider from being initialized more than once which could throw an error.
439+
*/
440+
if ($element.hasClass('slick-initialized')) {
441+
$element.slick('unslick');
442+
}
443+
444+
$element.slick({
445+
autoplay: $element.data('autoplay') === 1,
446+
autoplaySpeed: $element.data('autoplay-speed') || 0,
447+
fade: $element.data('fade') === 1,
448+
infinite: $element.data('is-infinite') === 1,
449+
arrows: $element.data('show-arrows') === 1,
450+
dots: $element.data('show-dots') === 1
451+
});
452+
};
453+
});
454+
455+
```
456+
457+
### Add XML configuration to load it on the frontend
458+
459+
To load this file on the frontend, add the following configuration to the `default.xml` file in your custom module's `frontend/layout/` directory:
460+
461+
``` xml
462+
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
463+
<body>
464+
<referenceBlock name="pagebuilder.widget.initializer">
465+
<arguments>
466+
<argument name="config" xsi:type="array">
467+
<item name="%content-type-name%" xsi:type="array">
468+
<item name="default" xsi:type="array">
469+
<!--required argument-->
470+
<item name="component" xsi:type="string">%{vendor-path}/js/content-type/{content-type-name}/appearance/{appearance-name}/widget%</item>
471+
<!--optional if you need provide some config for your widget-->
472+
<item name="config" xsi:type="array">
473+
<item name="buttonSelector" xsi:type="string">.pagebuilder-slide-button</item>
474+
<item name="showOverlay" xsi:type="string">hover</item>
475+
</item>
476+
<!--optional if you want load widget per appearance-->
477+
<item name="appearance" xsi:type="string">default</item>
478+
</item>
479+
</item>
480+
</argument>
481+
</arguments>
482+
</referenceBlock>
483+
</body>
484+
</page>
485+
```
486+
409487
## Converter Interfaces
410488

411489
Converter and mass converter are the two types of converters. Both converters expect `fromDom` and `toDom` methods, with usage examples described below.

app/code/Magento/PageBuilder/view/frontend/layout/default.xml

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,59 @@
66
*/
77
-->
88
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
9-
<head>
10-
<link src="Magento_PageBuilder::js/default.js"/>
11-
</head>
9+
<body>
10+
<referenceBlock name="head.components">
11+
<block class="Magento\PageBuilder\Block\WidgetInitializer" name="pagebuilder.widget.initializer" template="Magento_PageBuilder::widget_initializer.phtml">
12+
<arguments>
13+
<argument name="config" xsi:type="array">
14+
<item name="slider" xsi:type="array">
15+
<item name="default" xsi:type="array">
16+
<item name="component" xsi:type="string">Magento_PageBuilder/js/content-type/slider/appearance/default/widget</item>
17+
<!--optional if you want load widget per appearance-->
18+
<item name="appearance" xsi:type="string">default</item>
19+
</item>
20+
</item>
21+
<item name="map" xsi:type="array">
22+
<item name="default" xsi:type="array">
23+
<item name="component" xsi:type="string">Magento_PageBuilder/js/content-type/map/appearance/default/widget</item>
24+
</item>
25+
</item>
26+
<item name="row" xsi:type="array">
27+
<item name="default" xsi:type="array">
28+
<item name="component" xsi:type="string">Magento_PageBuilder/js/content-type/row/appearance/default/widget</item>
29+
</item>
30+
</item>
31+
<item name="tabs" xsi:type="array">
32+
<item name="default" xsi:type="array">
33+
<item name="component" xsi:type="string">Magento_PageBuilder/js/content-type/tabs/appearance/default/widget</item>
34+
</item>
35+
</item>
36+
<item name="slide" xsi:type="array">
37+
<item name="default" xsi:type="array">
38+
<!--required argument-->
39+
<item name="component" xsi:type="string">Magento_PageBuilder/js/widget/show-on-hover</item>
40+
<!--optional if you need provide some config for your widget-->
41+
<item name="config" xsi:type="array">
42+
<item name="buttonSelector" xsi:type="string">.pagebuilder-slide-button</item>
43+
<item name="showOverlay" xsi:type="string">hover</item>
44+
<item name="dataRole" xsi:type="string">slide</item>
45+
</item>
46+
</item>
47+
</item>
48+
<item name="banner" xsi:type="array">
49+
<item name="default" xsi:type="array">
50+
<item name="component" xsi:type="string">Magento_PageBuilder/js/widget/show-on-hover</item>
51+
<item name="config" xsi:type="array">
52+
<item name="buttonSelector" xsi:type="string">.pagebuilder-banner-button</item>
53+
<item name="showOverlay" xsi:type="string">on_hover</item>
54+
<item name="dataRole" xsi:type="string">banner</item>
55+
</item>
56+
</item>
57+
</item>
58+
</argument>
59+
</arguments>
60+
</block>
61+
</referenceBlock>
62+
</body>
1263
</page>
1364

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/** @var \Magento\PageBuilder\Block\WidgetInitializer $block */
8+
?>
9+
<script type="text/x-magento-init">
10+
{
11+
"*": {
12+
"Magento_PageBuilder/js/widget-initializer": {
13+
"config": <?= /* @noEscape */ $block->getConfig(); ?>
14+
}
15+
}
16+
}
17+
</script>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
define([
6+
'jquery',
7+
'Magento_PageBuilder/js/utils/map'
8+
], function ($, GoogleMap) {
9+
'use strict';
10+
11+
return function (config, element) {
12+
var locations,
13+
controls,
14+
mapOptions = {},
15+
$element = $(element);
16+
17+
/**
18+
* Sets height to 300px as default if no height input. But will not be saved to database
19+
*/
20+
if ($element.context.style.height === '') {
21+
$element.height('300px');
22+
}
23+
24+
if (element.hasAttribute('data-locations') && element.getAttribute('data-locations') !== '[]') {
25+
locations = JSON.parse(element.getAttribute('data-locations'));
26+
locations.forEach(function (location) {
27+
location.position.latitude = parseFloat(location.position.latitude);
28+
location.position.longitude = parseFloat(location.position.longitude);
29+
});
30+
controls = element.getAttribute('data-show-controls');
31+
mapOptions.center = locations[0].position;
32+
mapOptions.disableDefaultUI = controls !== 'true';
33+
mapOptions.mapTypeControl = controls === 'true';
34+
new GoogleMap(element, locations, mapOptions);
35+
}
36+
};
37+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
define([
6+
'jquery',
7+
'jarallax'
8+
], function ($) {
9+
'use strict';
10+
11+
return function (config, element) {
12+
var $element = $(element);
13+
14+
if ($element.data('enableParallax') !== 1) {
15+
return;
16+
}
17+
18+
$element.addClass('jarallax');
19+
$element.attr('data-jarallax', '');
20+
21+
window.jarallax(element, {
22+
imgPosition: element.style.backgroundPosition || '50% 50%',
23+
imgRepeat: element.style.backgroundRepeat || 'no-repeat',
24+
imgSize: element.style.backgroundSize || 'cover',
25+
speed: parseFloat($element.data('parallaxSpeed')) || 0.5
26+
});
27+
};
28+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
define([
7+
'jquery',
8+
'slick'
9+
], function ($) {
10+
'use strict';
11+
12+
return function (config, sliderElement) {
13+
14+
var $element = $(sliderElement);
15+
16+
/**
17+
* Prevent each slick slider from being initialized more than once which could throw an error.
18+
*/
19+
if ($element.hasClass('slick-initialized')) {
20+
$element.slick('unslick');
21+
}
22+
23+
$element.slick({
24+
autoplay: $element.data('autoplay') === 1,
25+
autoplaySpeed: $element.data('autoplay-speed') || 0,
26+
fade: $element.data('fade') === 1,
27+
infinite: $element.data('is-infinite') === 1,
28+
arrows: $element.data('show-arrows') === 1,
29+
dots: $element.data('show-dots') === 1
30+
});
31+
};
32+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
define([
6+
'jquery',
7+
'jquery/ui'
8+
], function ($) {
9+
'use strict';
10+
11+
return function (config, element) {
12+
var $element = $(element);
13+
14+
// Disambiguate between the mage/tabs component which is loaded randomly depending on requirejs order.
15+
$.ui.tabs({
16+
active: $element.data('activeTab') || 0,
17+
create:
18+
19+
/**
20+
* Adjust the margin bottom of the navigation to correctly display the active tab
21+
*/
22+
function () {
23+
var borderWidth = parseInt($element.find('.tabs-content').css('borderWidth').toString(), 10);
24+
25+
$element.find('.tabs-navigation').css('marginBottom', -borderWidth);
26+
$element.find('.tabs-navigation li:not(:first-child)').css('marginLeft', -borderWidth);
27+
}
28+
}, element);
29+
};
30+
});

0 commit comments

Comments
 (0)