Today, we will learn how can we add extra or custom content or media to Configurable Products’ Fotorama media gallery at the front end in visual and text swatches case.
Check our blog on Add Custom Content in Configurable Product Media Gallery in Magento 2 for drop-down swatch type.
In Magento 2, on the configurable product page, for rendering the swatch attributes, <magento-root-dir.>/vendor/magento/module-swatches/view/base/web/js/swatch-renderer.js file is responsible.
So, to add extra content in the configurable product’s media gallery(in text and visual swatch case), we need to override a few methods of the swatch-renderer js file.
For example, updateBaseImage, _onGalleryLoaded and _loadMedia functions are responsible for updating the media gallery after swatch rendering and swatch selection.
So, to add the custom content I have overridden the required functions and added some required files which are required to achieve our goal.
First of all, we will create a demo module. Here, I have created the Webkul_ExtraContentInFotorama module. Further, follow the below steps:
1. Create a di.xml file inside the <magento-root-dir>/app/code/Webkul/ExtraContentInFotorama/etc/ directory.
<?xml version="1.0"?> <!-- /** * Webkul Software. * * @category Webkul * @package Webkul_ExtraContentInFotorama * @author Webkul Software Private Limited * @copyright Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <!--Add Extra Configuration Data In JsonConfig--> <type name="Magento\ConfigurableProduct\Block\Product\View\Type\Configurable"> <plugin name="Wk_afterGetJsonConfig" type="Webkul\ExtraContentInFotorama\Plugin\ConfigurableProduct\Block\ConfigurableAfterGetJsonConfigPlugin" sortOrder="50" /> </type> </config>
2. Create ConfigurableAfterGetJsonConfigPlugin.php file inside the <magento-root-dir>/app/code/Webkul/ExtraContentInFotorama/Plugin/ConfigurableProduct/Block/ directory.
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_ExtraContentInFotorama * @author Webkul Software Private Limited * @copyright Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\ExtraContentInFotorama\Plugin\ConfigurableProduct\Block; class ConfigurableAfterGetJsonConfigPlugin { /** * @var \Magento\Framework\App\RequestInterface */ protected $request; /** * @var \Magento\Framework\Json\Helper\Data */ protected $jsonHelper; /** * Initialize dependencies * * @param \Magento\Framework\Json\Helper\Data $jsonHelper * @param \Magento\Framework\App\RequestInterface $request * @return void */ public function __construct( \Magento\Framework\Json\Helper\Data $jsonHelper, \Magento\Framework\App\RequestInterface $request ) { $this->request = $request; $this->jsonHelper = $jsonHelper; } /** * Composes configuration for js * * @param \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject * @param string $resultJson * @return string */ public function afterGetJsonConfig( \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable $subject, $resultJson ) { //Check if request is made from product page// if (strtolower($this->request->getFullActionName()) == "catalog_product_view") { $result = $this->jsonHelper->jsonDecode($resultJson); /////Set Extra Configuration Data///// $customConfig = []; $customConfig["linkUrl"] = "https://webkul.com/blog/design-patterns-in-magento-2/"; $customConfig["thumbnailImage"] = "Provide a thumbnail Image URL"; $customConfig["linkContent"] = "Design Patterns in Magento 2"; //set super attribute id, on which selection you want to change the content// $customConfig["defaultVariantAttribute"] = 138; $result["customConfig"] = $customConfig; $resultJson = $this->jsonHelper->jsonEncode($result); ///////// } return $resultJson; } }
3. Create a requires-config.js file to mention the mixin file for the swatch-renderer.js file inside the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/view/frontend/ directory.
/** * Webkul Software. * * @category Webkul * @package Webkul_ExtraContentInFotorama * @author Webkul Software Private Limited * @copyright Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ var config = { config: { mixins: { 'Magento_Swatches/js/swatch-renderer' : {'Webkul_ExtraContentInFotorama/js/swatch-renderer':true} } } };
4. Create a swatch-renderer.js file inside the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/view/frontend/web/js/ directory.
/** * Webkul Software. * * @category Webkul * @package Webkul_ExtraContentInFotorama * @author Webkul Software Private Limited * @copyright Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ define([ 'jquery', 'underscore', 'mage/translate' ], function ($, _, $t) { 'use strict'; return function (SwatchRenderer) { $.widget('mage.SwatchRenderer', SwatchRenderer, { /** * Update [gallery-placeholder] or [product-image-photo] * @param {Array} images * @param {jQuery} context * @param {Boolean} isInProductView */ updateBaseImage: function (images, context, isInProductView) { var self = this.options.jsonConfig.customConfig; //Load Custom Content Config. ///Check if linkUrl is empty// if (self.linkUrl == "" || self.linkUrl == null) { return this._super(images, context, isInProductView); } ///// var justAnImage = images[0], initialImages = this.options.mediaGalleryInitial, imagesToUpdate, gallery = context.find(this.options.mediaGallerySelector).data('gallery'), isInitial; if (isInProductView) { if (_.isUndefined(gallery)) { context.find(this.options.mediaGallerySelector).on('gallery:loaded', function () { this.updateBaseImage(images, context, isInProductView); }.bind(this)); return; } imagesToUpdate = images.length ? this._setImageType($.extend(true, [], images)) : []; isInitial = _.isEqual(imagesToUpdate, initialImages); if (this.options.gallerySwitchStrategy === 'prepend' && !isInitial) { //Remove Additional Extra Content initialImages = this._removeExtraContentfromArray(initialImages); ////////////// imagesToUpdate = imagesToUpdate.concat(initialImages); } imagesToUpdate = this._setImageIndex(imagesToUpdate); gallery.updateData(imagesToUpdate); this._addFotoramaVideoEvents(isInitial); } else if (justAnImage && justAnImage.img) { context.find('.product-image-photo').attr('src', justAnImage.img); } }, /** * Callback which fired after gallery gets initialized. * * @param {HTMLElement} element - DOM element associated with a gallery. */ _onGalleryLoaded: function (element) { var galleryObject = element.data('gallery'); //////////// var currImgs = galleryObject.returnCurrentImages(); //Load Extra Content// this._loadExtraContent(); //Push Extra Content in images gallery var self = this.options.jsonConfig.customConfig; var modelThumbnailImg = self.thumbnailImage; this._pushExtraContent(currImgs, modelThumbnailImg); ////////////////// this.options.mediaGalleryInitial = currImgs; ///Update Current Images in Media Gallery/// galleryObject.updateData(currImgs); }, /** * Load media gallery using ajax or json config. * * @private */ _loadMedia: function () { var self = this.options.jsonConfig.customConfig; //Get Custom Config. var $main = this.inProductList ? this.element.parents('.product-item-info') : this.element.parents('.column.main'), images; if (this.options.useAjax) { this._debouncedLoadProductMedia(); } else { images = this.options.jsonConfig.images[this.getProduct()]; if (!images) { images = this.options.mediaGalleryInitial; } ////////////Load Extra Content///// this._loadExtraContent(); //Remove Extra Content from image array images = this._removeExtraContentfromArray(images); var self = this.options.jsonConfig.customConfig; var modelThumbnailImg = self.thumbnailImage; //Push Extra Content from image array this._pushExtraContent(images, modelThumbnailImg); ////////////////// this.updateBaseImage(this._sortImages(images), $main, !this.inProductList); } }, /** * Delete Additional Extra Content from array * * @param {Array} imagesArray * @returns {Array} * @private */ _removeExtraContentfromArray: function(imagesArray) { imagesArray = imagesArray.filter(element => element.type !== "ExtraContent"); return imagesArray; }, /** * Push Extra Content in array * * @param {Array} fotoramaContentArray * @param {string} modelThumbnailImg * @private */ _pushExtraContent: function(fotoramaContentArray, modelThumbnailImg) { var self = this.options.jsonConfig.customConfig; if (typeof fotoramaContentArray != "undefined" && (self.linkUrl != "" || self.linkUrl != null)) { fotoramaContentArray.unshift({ thumb: modelThumbnailImg, src: self.linkUrl, type: 'ExtraContent', caption: self.linkContent, isMain: "true", position: 0 }); } }, /** * Get Selected Variant Value * * @return {string} * @private */ _getSelectedVariantValue: function() { var self = this.options.jsonConfig.customConfig; var optionTextVal = ""; var optionTextArr = []; var selectedText = ""; var selectedVal = ""; var selectedSwatchAttrId = 0; var defaultVariantAttribute = self.defaultVariantAttribute; if ($('.product-options-wrapper select[id^="attribute"]').find().length) { selectedText = $('.product-options-wrapper select[id^="attribute"] option:selected').text(); } else { if ($('.swatch-attribute-options .swatch-option[aria-checked="true"]').length) { var swatchId = ""; var idParts = []; $('.swatch-attribute-options .swatch-option[aria-checked="true"]').each(function() { swatchId = $(this).attr("id"); idParts = swatchId.split('-'); for (let index=0; index<idParts.length; index++) { if ($.isNumeric(idParts[index])) { selectedSwatchAttrId = idParts[index]; break; } } if (parseInt(defaultVariantAttribute) == selectedSwatchAttrId) { selectedText = $(this).attr("data-option-label"); } }); } } /////Get Selected Variant Value///// selectedVal = $('.product-options-wrapper select[id^="attribute"] option:selected').val(); if (selectedVal == "" && $('.product-options-wrapper select[id^="attribute"]').find().length) { selectedText = $('.product-options-wrapper select[id^="attribute"] option:eq(1)').text(); } else { selectedVal = selectedText; } ///// if ($('.product-options-wrapper select[id^="attribute"]').find().length) { if (selectedText.indexOf('+') == -1) { optionTextVal = selectedText; } else { optionTextArr = selectedText.split('+'); optionTextVal = $.trim(optionTextArr[0]); } } else { optionTextVal = selectedVal; } return optionTextVal; }, /** * Event for swatch options * * @param {Object} $this * @param {Object} $widget * @private */ _OnClick: function ($this, $widget) { var self = this.options.jsonConfig.customConfig; var wkExtraContentDiv = $("#wkExtraContent"); var mainVariantAttributeId = self.defaultVariantAttribute; var swatchId = $this.attr("id"); var idParts = swatchId.split('-'); var selectedSwatchAttrId = 0; for (let index=0; index<idParts.length; index++) { if ($.isNumeric(idParts[index])) { selectedSwatchAttrId = idParts[index]; break; } } if (typeof wkExtraContentDiv == "object" && selectedSwatchAttrId == parseInt(mainVariantAttributeId)) { var label = $this.attr("data-option-label"); var bgColor = "#86FA50"; switch (label) { case 'Gold': bgColor = "#DFD906"; break; case 'Diamond': bgColor = "#AFF3F2"; break; } setTimeout(function(){ $("#wkExtraContent").css("background-color", bgColor); }, 300); } this._super($this, $widget); }, /** * Load Extra Content * * @private */ _loadExtraContent: function() { var thisJs = this; var self = this.options.jsonConfig.customConfig; var divFotorama = $('div.gallery-placeholder > div.fotorama'); if (self.linkUrl == "") { return; } var variantText = "None"; //Get Selected Variant Value variantText = thisJs._getSelectedVariantValue(); divFotorama.on('fotorama:load', function fotorama_onLoad(e, fotorama, extra) { if (extra.frame.type === 'ExtraContent' && extra.frame.src != "") { var extraContentHtml = ''; extraContentHtml += '<div id="wkExtraContent" style="background-color:#86FA50">'; extraContentHtml += '<h1 style="margin-top:250px">'+'Extra Content'+'</h1>'; ///Show Variant Text/// if (variantText != '') { extraContentHtml += '<p style="font-size:20px">Selected Variant:</p>'; extraContentHtml += '<p style="font-size:18px">'+variantText+'</p><br/>'; } ///////////////// extraContentHtml += '<a href="'+self.linkUrl+'" style="font-size:18px">' extraContentHtml += self.linkContent+'</a>'; extraContentHtml += '</div>'; extra.frame.$stageFrame.html(extraContentHtml); } }); } }); return $.mage.SwatchRenderer; }; });
5. After adding the above code to your module. Deploy the code and see the result in the text swatch case. Refer to the below images for the result.
6. See the result in the visual swatch case. Refer to the below images for the result.
Note: Remember to add <sequence> in the module.xml file to load the Magento_Swatches module before your custom module.
Check the Magento 2 Advanced Media Manager extension that allows editing the images present in the media gallery and add watermarks, filter, rotate, resize, and more.
Hire Magento developers who are dedicated to achieving outstanding outcomes for your unique e-commerce ventures in order to add a personal touch.
Additionally, there is no need to search further; seize the chance to kickstart your projects with the suggested Magento development company.
Be the first to comment.