Hi Buddies, on this weblog, we can learn the way are we able to upload additional or customized content material or media to Configurable Merchandise’ Fotorama media gallery on the entrance lead to visible and textual content swatches case.
For dropdown swatch sort, take a look at our weblog Upload Customized Content material in Configurable Product Media Gallery – Magento 2
In Magento 2, at the configurable product web page, for rendering the swatch attributes, <magento-root-dir.>/seller/magento/module-swatches/view/base/internet/js/swatch-renderer.js report is accountable.
So, so as to add additional content material within the configurable product’s media gallery(in textual content and visible swatch case), we wish to override a couple of strategies of the swatch-renderer js report.
For instance, updateBaseImage, _onGalleryLoaded and _loadMedia purposes are liable for updating the media gallery after swatch rendering and swatch variety.
So, so as to add the customized content material I’ve overridden the desired purposes and added some required information which can be required to succeed in our objective.
Initially, we can create a demo module. Right here, I’ve created the Webkul_ExtraContentInFotorama module. Additional, observe the beneath steps:
1. Create a di.xml report within the <magento-root-dir>/app/code/Webkul/ExtraContentInFotorama/and so forth/ listing.
<?xml model="1.0"?> <!-- /** * Webkul Tool. * * @class Webkul * @bundle Webkul_ExtraContentInFotorama * @creator Webkul Tool Non-public Restricted * @copyright Webkul Tool Non-public Restricted (https://webkul.com) * @license https://retailer.webkul.com/license.html */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/and so forth/config.xsd"> <!--Upload Additional Configuration Information In JsonConfig--> <sort title="MagentoConfigurableProductBlockProductViewTypeConfigurable"> <plugin title="Wk_afterGetJsonConfig" sort="WebkulExtraContentInFotoramaPluginConfigurableProductBlockConfigurableAfterGetJsonConfigPlugin" sortOrder="50" /> </sort> </config>
2. Create ConfigurableAfterGetJsonConfigPlugin.php report within the <magento-root-dir>/app/code/Webkul/ExtraContentInFotorama/Plugin/ConfigurableProduct/Block/ listing.
<?php /** * Webkul Tool. * * @class Webkul * @bundle Webkul_ExtraContentInFotorama * @creator Webkul Tool Non-public Restricted * @copyright Webkul Tool Non-public Restricted (https://webkul.com) * @license https://retailer.webkul.com/license.html */ namespace WebkulExtraContentInFotoramaPluginConfigurableProductBlock; magnificence ConfigurableAfterGetJsonConfigPlugin { /** * @var MagentoFrameworkAppRequestInterface */ secure $request; /** * @var MagentoFrameworkJsonHelperData */ secure $jsonHelper; /** * Initialize dependencies * * @param MagentoFrameworkJsonHelperData $jsonHelper * @param MagentoFrameworkAppRequestInterface $request * @go back void */ public serve as __construct( MagentoFrameworkJsonHelperData $jsonHelper, MagentoFrameworkAppRequestInterface $request ) { $this->request = $request; $this->jsonHelper = $jsonHelper; } /** * Composes configuration for js * * @param MagentoConfigurableProductBlockProductViewTypeConfigurable $topic * @param string $resultJson * @go back string */ public serve as afterGetJsonConfig( MagentoConfigurableProductBlockProductViewTypeConfigurable $topic, $resultJson ) { //Test if request is comprised of product web page// if (strtolower($this->request->getFullActionName()) == "catalog_product_view") { $consequence = $this->jsonHelper->jsonDecode($resultJson); /////Set Additional Configuration Information///// $customConfig = []; $customConfig["linkUrl"] = "https://webkul.com/weblog/design-patterns-in-magento-2/"; $customConfig["thumbnailImage"] = "Supply a thumbnail Symbol URL"; $customConfig["linkContent"] = "Design Patterns in Magento 2"; //set tremendous characteristic identity, on which variety you wish to have to modify the content material// $customConfig["defaultVariantAttribute"] = 138; $consequence["customConfig"] = $customConfig; $resultJson = $this->jsonHelper->jsonEncode($consequence); ///////// } go back $resultJson; } }
3. Create a requires-config.js report to say the mixin report for the swatch-renderer.js report within the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/view/frontend/ listing.
/** * Webkul Tool. * * @class Webkul * @bundle Webkul_ExtraContentInFotorama * @creator Webkul Tool Non-public Restricted * @copyright Webkul Tool Non-public Restricted (https://webkul.com) * @license https://retailer.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 report within the <magento-root-dir.>/app/code/Webkul/ExtraContentInFotorama/view/frontend/internet/js/ listing.
/** * Webkul Tool. * * @class Webkul * @bundle Webkul_ExtraContentInFotorama * @creator Webkul Tool Non-public Restricted * @copyright Webkul Tool Non-public Restricted (https://webkul.com) * @license https://retailer.webkul.com/license.html */ outline([ 'jquery', 'underscore', 'mage/translate' ], serve as ($, _, $t) { 'use strict'; go back serve as (SwatchRenderer) { $.widget('mage.SwatchRenderer', SwatchRenderer, { /** * Replace [gallery-placeholder] or [product-image-photo] * @param {Array} pictures * @param {jQuery} context * @param {Boolean} isInProductView */ updateBaseImage: serve as (pictures, context, isInProductView) { var self = this.solutions.jsonConfig.customConfig; //Load Customized Content material Config. ///Test if linkUrl is empty// if (self.linkUrl == "" || self.linkUrl == null) { go back this._super(pictures, context, isInProductView); } ///// var justAnImage = pictures[0], initialImages = this.solutions.mediaGalleryInitial, imagesToUpdate, gallery = context.in finding(this.solutions.mediaGallerySelector).information('gallery'), isInitial; if (isInProductView) { if (_.isUndefined(gallery)) { context.in finding(this.solutions.mediaGallerySelector).on('gallery:loaded', serve as () { this.updateBaseImage(pictures, context, isInProductView); }.bind(this)); go back; } imagesToUpdate = pictures.duration ? this._setImageType($.lengthen(true, [], pictures)) : []; isInitial = _.isEqual(imagesToUpdate, initialImages); if (this.solutions.gallerySwitchStrategy === 'prepend' && !isInitial) { //Take away Further Additional Content material initialImages = this._removeExtraContentfromArray(initialImages); ////////////// imagesToUpdate = imagesToUpdate.concat(initialImages); } imagesToUpdate = this._setImageIndex(imagesToUpdate); gallery.updateData(imagesToUpdate); this._addFotoramaVideoEvents(isInitial); } else if (justAnImage && justAnImage.img) { context.in finding('.product-image-photo').attr('src', justAnImage.img); } }, /** * Callback which fired after gallery will get initialized. * * @param {HTMLElement} part - DOM part related to a gallery. */ _onGalleryLoaded: serve as (part) { var galleryObject = part.information('gallery'); //////////// var currImgs = galleryObject.returnCurrentImages(); //Load Additional Content material// this._loadExtraContent(); //Push Additional Content material in pictures gallery var self = this.solutions.jsonConfig.customConfig; var modelThumbnailImg = self.thumbnailImage; this._pushExtraContent(currImgs, modelThumbnailImg); ////////////////// this.solutions.mediaGalleryInitial = currImgs; ///Replace Present Photographs in Media Gallery/// galleryObject.updateData(currImgs); }, /** * Load media gallery the use of ajax or json config. * * @personal */ _loadMedia: serve as () { var self = this.solutions.jsonConfig.customConfig; //Get Customized Config. var $primary = this.inProductList ? this.part.oldsters('.product-item-info') : this.part.oldsters('.column.primary'), pictures; if (this.solutions.useAjax) { this._debouncedLoadProductMedia(); } else { pictures = this.solutions.jsonConfig.pictures[this.getProduct()]; if (!pictures) { pictures = this.solutions.mediaGalleryInitial; } ////////////Load Additional Content material///// this._loadExtraContent(); //Take away Additional Content material from picture array pictures = this._removeExtraContentfromArray(pictures); var self = this.solutions.jsonConfig.customConfig; var modelThumbnailImg = self.thumbnailImage; //Push Additional Content material from picture array this._pushExtraContent(pictures, modelThumbnailImg); ////////////////// this.updateBaseImage(this._sortImages(pictures), $primary, !this.inProductList); } }, /** * Delete Further Additional Content material from array * * @param {Array} imagesArray * @returns {Array} * @personal */ _removeExtraContentfromArray: serve as(imagesArray) { imagesArray = imagesArray.filter out(part => part.sort !== "ExtraContent"); go back imagesArray; }, /** * Push Additional Content material in array * * @param {Array} fotoramaContentArray * @param {string} modelThumbnailImg * @personal */ _pushExtraContent: serve as(fotoramaContentArray, modelThumbnailImg) { var self = this.solutions.jsonConfig.customConfig; if (typeof fotoramaContentArray != "undefined" && (self.linkUrl != "" || self.linkUrl != null)) { fotoramaContentArray.unshift({ thumb: modelThumbnailImg, src: self.linkUrl, sort: 'ExtraContent', caption: self.linkContent, isMain: "true", place: 0 }); } }, /** * Get Decided on Variant Worth * * @go back {string} * @personal */ _getSelectedVariantValue: serve as() { var self = this.solutions.jsonConfig.customConfig; var optionTextVal = ""; var optionTextArr = []; var selectedText = ""; var selectedVal = ""; var selectedSwatchAttrId = 0; var defaultVariantAttribute = self.defaultVariantAttribute; if ($('.product-options-wrapper choose[id^="attribute"]').in finding().duration) { selectedText = $('.product-options-wrapper choose[id^="attribute"] possibility:decided on').textual content(); } else { if ($('.swatch-attribute-options .swatch-option[aria-checked="true"]').duration) { var swatchId = ""; var idParts = []; $('.swatch-attribute-options .swatch-option[aria-checked="true"]').every(serve as() { swatchId = $(this).attr("identity"); idParts = swatchId.break up('-'); for (let index=0; index<idParts.duration; index++) { if ($.isNumeric(idParts[index])) { selectedSwatchAttrId = idParts[index]; spoil; } } if (parseInt(defaultVariantAttribute) == selectedSwatchAttrId) { selectedText = $(this).attr("data-option-label"); } }); } } /////Get Decided on Variant Worth///// selectedVal = $('.product-options-wrapper choose[id^="attribute"] possibility:decided on').val(); if (selectedVal == "" && $('.product-options-wrapper choose[id^="attribute"]').in finding().duration) { selectedText = $('.product-options-wrapper choose[id^="attribute"] possibility:eq(1)').textual content(); } else { selectedVal = selectedText; } ///// if ($('.product-options-wrapper choose[id^="attribute"]').in finding().duration) { if (selectedText.indexOf('+') == -1) { optionTextVal = selectedText; } else { optionTextArr = selectedText.break up('+'); optionTextVal = $.trim(optionTextArr[0]); } } else { optionTextVal = selectedVal; } go back optionTextVal; }, /** * Match for swatch solutions * * @param {Object} $this * @param {Object} $widget * @personal */ _OnClick: serve as ($this, $widget) { var self = this.solutions.jsonConfig.customConfig; var wkExtraContentDiv = $("#wkExtraContent"); var mainVariantAttributeId = self.defaultVariantAttribute; var swatchId = $this.attr("identity"); var idParts = swatchId.break up('-'); var selectedSwatchAttrId = 0; for (let index=0; index<idParts.duration; index++) { if ($.isNumeric(idParts[index])) { selectedSwatchAttrId = idParts[index]; spoil; } } if (typeof wkExtraContentDiv == "object" && selectedSwatchAttrId == parseInt(mainVariantAttributeId)) { var label = $this.attr("data-option-label"); var bgColor = "#86FA50"; transfer (label) { case 'Gold': bgColor = "#DFD906"; spoil; case 'Diamond': bgColor = "#AFF3F2"; spoil; } setTimeout(serve as(){ $("#wkExtraContent").css("background-color", bgColor); }, 300); } this._super($this, $widget); }, /** * Load Additional Content material * * @personal */ _loadExtraContent: serve as() { var thisJs = this; var self = this.solutions.jsonConfig.customConfig; var divFotorama = $('div.gallery-placeholder > div.fotorama'); if (self.linkUrl == "") { go back; } var variantText = "None"; //Get Decided on Variant Worth variantText = thisJs._getSelectedVariantValue(); divFotorama.on('fotorama:load', serve as fotorama_onLoad(e, fotorama, additional) { if (additional.body.sort === 'ExtraContent' && additional.body.src != "") { var extraContentHtml = ''; extraContentHtml += '<div identity="wkExtraContent" taste="background-color:#86FA50">'; extraContentHtml += '<h1 taste="margin-top:250px">'+'Additional Content material'+'</h1>'; ///Display Variant Textual content/// if (variantText != '') { extraContentHtml += '<p taste="font-size:20px">Decided on Variant:</p>'; extraContentHtml += '<p taste="font-size:18px">'+variantText+'</p><br/>'; } ///////////////// extraContentHtml += '<a href="'+self.linkUrl+'" taste="font-size:18px">' extraContentHtml += self.linkContent+'</a>'; extraContentHtml += '</div>'; additional.body.$stageFrame.html(extraContentHtml); } }); } }); go back $.mage.SwatchRenderer; }; });
5. After including the above code in your module. Deploy the code and spot the outcome within the textual content swatch case. Discuss with the beneath pictures for the outcome.


6. See the outcome within the visible swatch case. Discuss with the beneath pictures for the outcome.


Be aware: Have in mind so as to add <collection> within the module.xml report to load the Magento_Swatches module ahead of your customized module.
You might also take a look at the Magento 2 Complicated Media Supervisor extension to edit the photographs provide within the media gallery and upload watermarks, filter out, rotate, resize, and extra.