Error executing template "/Designs/Swift/Grid/Page/RowTemplates/1Column.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at Dynamicweb.Content.Items.Metadata.FieldOptionMetadataItemSource.get_Values() at Dynamicweb.Content.Items.Editors.ListEditor`1.ViewModelOptionsFactory(List`1 converted, ItemField field, Boolean allowSorting) at Dynamicweb.Frontend.ListViewModel.get_Options() at Dynamicweb.Frontend.ListViewModel.get_SelectedOptions() at Dynamicweb.Frontend.ListViewModel.get_SelectedValues() at CompiledRazorTemplates.Dynamic.RazorEngine_43ca7521074c4ac9bf4e051dfc1eb991.Execute() in F:\Domains\Sites\uat-ic.mydwsite.com\Files\Templates\Designs\Swift\Grid\Page\RowTemplates\1Column.cshtml:line 122 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.GridRowViewModel> 2 3 @{ 4 string sectionClass = "py-3"; 5 string spaceBetweenRows = Model.Item.GetRawValueString("SpaceBetweenRows", "spacing"); 6 string spaceBetweenRowsMobile = Model.Item.GetRawValueString("SpaceBetweenRowsMobile", "auto"); 7 8 //Row spacing mobile auto 9 if (spaceBetweenRowsMobile == "auto") { 10 spaceBetweenRowsMobile = spaceBetweenRows; 11 } 12 13 //Row spacing mobile 14 switch (spaceBetweenRowsMobile) { 15 case "none": //No spacing 16 sectionClass = "py-0"; 17 break; 18 case "spacing": //Small spacing top and bottom 19 sectionClass = "py-3"; 20 break; 21 case "spacing-small-top": //Small spacing top 22 sectionClass = "pt-3"; 23 break; 24 case "spacing-small-bottom": //Small spacing bottom 25 sectionClass = "pb-3"; 26 break; 27 case "spacing-medium": //Medium spacing top and bottom 28 sectionClass = "py-4"; 29 break; 30 case "spacing-medium-top": //Medium spacing top 31 sectionClass = "pt-4"; 32 break; 33 case "spacing-medium-bottom": //Medium spacing bottom 34 sectionClass = "pb-4"; 35 break; 36 case "spacing-large": //Large spacing top and bottom 37 sectionClass = "py-5"; 38 break; 39 case "spacing-top": //Large spacing top 40 sectionClass = "pt-5"; 41 break; 42 case "spacing-bottom": //Large spacing bottom 43 sectionClass = "pb-5"; 44 break; 45 } 46 47 //Row spacing dekstop 48 switch (spaceBetweenRows) { 49 case "none": //No spacing 50 sectionClass += " py-lg-0"; 51 break; 52 case "spacing": //Small spacing top and bottom 53 sectionClass += " py-lg-3"; 54 break; 55 case "spacing-small-top": //Small spacing top 56 sectionClass += " pt-lg-3 pb-lg-0"; 57 break; 58 case "spacing-small-bottom": //Small spacing bottom 59 sectionClass += " pb-lg-3 pt-lg-0"; 60 break; 61 case "spacing-medium": //Medium spacing top and bottom 62 sectionClass += " py-lg-5"; 63 break; 64 case "spacing-medium-top": //Medium spacing top 65 sectionClass += " pt-lg-5 pb-lg-0"; 66 break; 67 case "spacing-medium-bottom": //Medium spacing bottom 68 sectionClass += " pb-lg-5 pt-lg-0"; 69 break; 70 case "spacing-large": //Large spacing top and bottom 71 sectionClass += " py-lg-6"; 72 break; 73 case "spacing-top": //Large spacing top 74 sectionClass += " pt-lg-6 pb-lg-0"; 75 break; 76 case "spacing-bottom": //Large spacing bottom 77 sectionClass += " pb-lg-6 pt-lg-0"; 78 break; 79 } 80 81 string width = Model.Item.GetRawValueString("Width"); 82 string containerClass = "container-xl"; 83 if (width == "stretch") 84 { 85 containerClass = "container-fluid"; 86 } 87 if (width == "none") 88 { 89 containerClass = "container-fluid px-0"; 90 } 91 if (width == "compressed") 92 { 93 containerClass = " container-compressed"; 94 } 95 96 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 97 98 string animationOnScrollCol1 = Model.Item.GetRawValueString("AnimationOnScroll", "no-animation"); 99 animationOnScrollCol1 = animationOnScrollCol1 != "no-animation" ? "data-aos=" + "'" + animationOnScrollCol1 + "'" : ""; 100 101 string hideOverflow = " overflow-hidden"; 102 hideOverflow = animationOnScrollCol1 != "" ? hideOverflow : ""; 103 104 Dynamicweb.Frontend.FileViewModel backgroundImage = Model.Item.GetFile("BackgroundImage"); 105 string backgroundImagePath = backgroundImage?.Path ?? string.Empty; 106 string imagePath = $"/Admin/Public/GetImage.ashx?image={backgroundImagePath}&width=960&format=webp"; 107 backgroundImagePath = Dynamicweb.Core.Encoders.HtmlEncoder.UrlPathEncode(backgroundImagePath); 108 string backgroundRepeat = Model.Item.GetRawValueString("BackgroundImageRepeat", "no-repeat"); 109 string backgroundImageSize = Model.Item.GetRawValueString("BackgroundImageSize", "initial"); 110 int xPos = backgroundImage?.FocalPositionFromLeft ?? 50; 111 int yPos = backgroundImage?.FocalPositionFromTop ?? 50; 112 string cssPosition = $"{xPos}% {yPos}%"; 113 string gradient = Model.Item.GetRawValueString("Gradient", string.Empty); 114 string gradientOpacity = Model.Item.GetRawValueString("GradientOpacity", "0.00"); 115 string gradientString = "linear-gradient(" + gradient + "deg," + "rgba(var(--swift-foreground-color-rgb)," + gradientOpacity + "), rgba(var(--swift-background-color-rgb)," + gradientOpacity + "))"; 116 string backgroundImageString = "url(" + backgroundImagePath + ")"; 117 string backgroundImagePositionString = "background-position:" + cssPosition + ";"; 118 string backgroundRepeatString = "background-repeat:" + backgroundRepeat + ";"; 119 string backgroundImageSizeString = "background-size:" + backgroundImageSize + ";"; 120 string styleString = string.Empty; 121 122 var decorations = Model.Item?.GetList("CssDecorations")?.SelectedValues ?? Enumerable.Empty<string>(); 123 var css = string.Empty; 124 var cssClasses = new List<string> { }; 125 126 foreach (var itemId in decorations) 127 { 128 var item = Dynamicweb.Content.Services.Items.GetItem("Swift_Css", itemId); 129 item.TryGetValue("Class", out object classes); 130 if (classes is null) 131 { 132 continue; 133 } 134 135 var cssString = (string)classes; 136 if (cssString.StartsWith("[")) 137 { 138 var cssArray = Dynamicweb.Core.Converter.Deserialize<string[]>(cssString); 139 cssClasses.AddRange(cssArray); 140 } 141 else 142 { 143 cssClasses.Add(cssString.Replace(",", " ")); 144 } 145 } 146 css = string.Join(" ", cssClasses).Trim(); 147 148 @* Only gradient *@ 149 150 if (!string.IsNullOrEmpty(gradient) && string.IsNullOrEmpty(backgroundImagePath) && gradientOpacity != ("0.00")) 151 { 152 styleString += "style=\"background-image:" + gradientString + ";\""; 153 } 154 155 @* Only background image *@ 156 157 else if (string.IsNullOrEmpty(gradient) && !string.IsNullOrEmpty(backgroundImagePath)) 158 { 159 styleString += "style=\"background-image:" + backgroundImageString + "," + backgroundImagePositionString + backgroundRepeatString + backgroundImageSizeString + "\""; 160 } 161 162 @* Gradient and background image *@ 163 164 else if (!string.IsNullOrEmpty(gradient) && !string.IsNullOrEmpty(backgroundImagePath)) 165 { 166 styleString += "style=\"background-image:" + gradientString + "," + backgroundImageString + ";" + backgroundImagePositionString + backgroundRepeatString + backgroundImageSizeString + "\""; 167 } 168 169 if (Pageview.IsVisualEditorMode || !string.IsNullOrWhiteSpace(Model.Column(1).Output())) 170 { 171 <div class="@(sectionClass)@(theme) @(css) item_@Model.Item.SystemName.ToLower()" @styleString> 172 <div class="@containerClass@(hideOverflow)"> 173 <div class="grid grid-1"> 174 <div class="g-col" data-col-size="12" @animationOnScrollCol1 style="--bs-columns:12"> 175 @Model.Column(1).Output() 176 </div> 177 </div> 178 </div> 179 </div> 180 } 181 } 182
Please Login to see pricing.
Expected back in stock:
Error executing template "Designs/Swift/Paragraph/Custom__ShipDate.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_268baf4bb8a54c1babf3dc4c2e5756e5.Execute() in F:\Domains\Sites\uat-ic.mydwsite.com\Files\Templates\Designs\Swift\Paragraph\Custom__ShipDate.cshtml:line 32 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @* 2 Ian notes 8/12/2025: pulled in the manual expected date using the line "DateTime? ManualDate =...", the added the integration expected date using "DateTime? ExpectedDate =...", 3 then created DisplayDateValue so it would only show 1 of the dates and edited the bool section so it would look at displaydatevalue. 4 5 Also, can use template in the future when trying to pull a custom field into a template, use the manual date as example. 6 *@ 7 8 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 9 @using System 10 @using System.Linq 11 @using Dynamicweb.Ecommerce.ProductCatalog 12 13 @{ 14 ProductViewModel product = null; 15 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 16 { 17 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 18 } 19 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 20 { 21 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 22 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 23 24 if (productList?.Products is object) 25 { 26 product = productList.Products[0]; 27 } 28 } 29 30 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 31 bool hideStock = Pageview.AreaSettings.GetBoolean("ErpDownHideStock") && isErpConnectionDown; 32 DateTime? ManualDate = product.ProductFields.ContainsKey("ManualProductExpectedDelivery") && DateTime.TryParse(product.ProductFields["ManualProductExpectedDelivery"]?.ToString(), out var dt) ? dt : (DateTime?)null; 33 DateTime? ExpectedDate = product.ExpectedDelivery; 34 DateTime? DisplayDateValue = ExpectedDate ?? ManualDate; 35 bool hasDisplayDate = DisplayDateValue != null && DisplayDateValue > DateTime.Now; 36 } 37 38 39 @if ((product is object && !hideStock) && (hasDisplayDate)) 40 { 41 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", ""); 42 horizontalAlign = horizontalAlign == "center" ? "text-center" : horizontalAlign; 43 horizontalAlign = horizontalAlign == "end" ? "text-end" : horizontalAlign; 44 string DisplayDate = DisplayDateValue?.ToShortDateString() ?? ""; 45 46 string liveInfoClass = ""; 47 string productInfoFeed = ""; 48 bool isLazyLoadingForProductInfoEnabled = Dna.Ecommerce.LiveIntegration.TemplatesHelper.IsLazyLoadingForProductInfoEnabled; 49 50 if (isLazyLoadingForProductInfoEnabled) 51 { 52 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 53 { 54 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 55 if (!string.IsNullOrEmpty(productInfoFeed)) 56 { 57 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 58 } 59 } 60 liveInfoClass = "js-live-info"; 61 62 <div class="js-stock-state @horizontalAlign item_@Model.Item.SystemName.ToLower() @liveInfoClass" data-product-id="@product.Id" data-variant-id="@product.VariantId" @productInfoFeed> 63 <div class="js-stock-state spinner-border"> 64 <p class="d-none" data-show-if="LiveProductInfo.product.StockLevel <= 0"> 65 <span class="js-text-stock d-none"></span> 66 <span>@Translate("Expected Ship Date"): </span> 67 <span>@DisplayDate</span> 68 </p> 69 </div> 70 </div> 71 } 72 else 73 { 74 string firstUnitId = product?.UnitOptions?.FirstOrDefault() != null ? product.UnitOptions.FirstOrDefault().Id : ""; 75 string defaultUnitId = !string.IsNullOrEmpty(product.DefaultUnitId) ? product.DefaultUnitId : firstUnitId; 76 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : defaultUnitId; 77 78 var reserveMode = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.Mode; 79 double? reservedAmount = 0; 80 if (reserveMode == Dynamicweb.Ecommerce.Frontend.Cart.ProductReserveMode.AddToCart) 81 { 82 reservedAmount = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.GetReservedAmount(product.Id, product.VariantId, 0, unitId); 83 } 84 double? currentStockLevel = product.StockLevel - reservedAmount; 85 86 <div class="js-stock-state @horizontalAlign item_@Model.Item.SystemName.ToLower()"> 87 @if (currentStockLevel <= 0) 88 { 89 <p> 90 <span>@Translate("Expected Ship Date"): </span> 91 <span>@DisplayDate</span> 92 </p> 93 } 94 </div> 95 } 96 } else if (Pageview.IsVisualEditorMode) 97 { 98 <div class="alert alert-info">@Translate("Expected Ship Date will be rendered here")</div> 99 }
Error executing template "Designs/Swift/Paragraph/Swift_ProductDetailsGallery.cshtml" System.ArgumentNullException: Value cannot be null. Parameter name: source at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate) at CompiledRazorTemplates.Dynamic.RazorEngine_3b64be1743a548268ba09c0508716868.Execute() in F:\Domains\Sites\uat-ic.mydwsite.com\Files\Templates\Designs\Swift\Paragraph\Swift_ProductDetailsGallery.cshtml:line 110 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Frontend 4 @using System.IO 5 6 @functions { 7 public ProductViewModel product { get; set; } = new ProductViewModel(); 8 public string galleryLayout { get; set; } 9 public string[] supportedImageFormats { get; set; } 10 public string[] supportedVideoFormats { get; set; } 11 public string[] supportedDocumentFormats { get; set; } 12 public string[] allSupportedFormats { get; set; } 13 14 public class RatioSettings { 15 public string Ratio { get; set; } 16 public string CssClass { get; set; } 17 public string CssVariable { get; set; } 18 public string Fill { get; set; } 19 } 20 21 public RatioSettings GetRatioSettings(string size = "desktop") { 22 var ratioSettings = new RatioSettings(); 23 24 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 25 ratio = ratio != "0" ? ratio : ""; 26 string cssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 27 string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : ""; 28 cssClass = ratio != "" && ratio == "fill" && size == "mobile" ? " ratio" : cssClass; 29 cssVariable = ratio != "" && ratio == "fill" && size == "mobile" ? "--bs-aspect-ratio: 66%" : cssVariable; 30 31 ratioSettings.Ratio = ratio; 32 ratioSettings.CssClass = cssClass; 33 ratioSettings.CssVariable = cssVariable; 34 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 35 36 return ratioSettings; 37 } 38 39 public string GetColumnClass(int total, int assetNumber) { 40 string colClass = total > 1 ? "g-col-lg-6" : "g-col-12"; 41 colClass = galleryLayout == "full-first" && assetNumber == 0 ? "g-col-12" : colClass; 42 colClass = galleryLayout == "full-last" && assetNumber == (total - 1) ? "g-col-12" : colClass; 43 colClass = galleryLayout == "advanced-grid" && assetNumber > 1 ? "g-col-4" : colClass; 44 45 colClass = galleryLayout == "advanced-grid" && total == 1 ? "g-col-12" : colClass; 46 colClass = galleryLayout == "advanced-grid" && total == 3 && assetNumber == 2 ? "g-col-12" : colClass; 47 colClass = galleryLayout == "advanced-grid" && total == 4 && assetNumber == 2 ? "g-col-6" : colClass; 48 colClass = galleryLayout == "advanced-grid" && total == 4 && assetNumber == 3 ? "g-col-6" : colClass; 49 colClass = galleryLayout == "advanced-grid" && total == 6 && assetNumber == 5 ? "g-col-12" : colClass; 50 colClass = galleryLayout == "advanced-grid" && total == 7 && assetNumber == 5 ? "g-col-6" : colClass; 51 colClass = galleryLayout == "advanced-grid" && total == 7 && assetNumber == 6 ? "g-col-6" : colClass; 52 colClass = galleryLayout == "advanced-grid" && total == 9 && assetNumber == 8 ? "g-col-12" : colClass; 53 54 return colClass; 55 } 56 57 public string GetArrowsColor() 58 { 59 var invertColor = Model.Item.GetBoolean("InvertModalArrowsColor"); 60 var arrowsColor = invertColor ? " carousel-dark" : string.Empty; 61 return arrowsColor; 62 } 63 64 Dictionary<string, object> GetVideoParams(MediaViewModel asset, string size) 65 { 66 var videoParams = new Dictionary<string, object>(); 67 videoParams.Add("AssetName", asset.Name); 68 videoParams.Add("AssetDisplayName", asset.DisplayName); 69 videoParams.Add("AssetValue", asset.Value); 70 videoParams.Add("OpenVideoInModal", Model.Item.GetString("OpenVideoInModal")); 71 videoParams.Add("VideoAutoPlay", Model.Item.GetBoolean("VideoAutoPlay")); 72 videoParams.Add("Size", size); 73 videoParams.Add("Id", Model.ID); 74 return videoParams; 75 } 76 } 77 78 @{ 79 @* Get the product data *@ 80 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 81 { 82 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 83 } 84 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 85 { 86 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 87 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 88 89 if (productList?.Products is object) 90 { 91 product = productList.Products[0]; 92 } 93 } 94 } 95 96 @if (product is object) 97 { 98 @* Supported formats *@ 99 supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" }; 100 supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" }; 101 supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" }; 102 allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray(); 103 104 @* Collect the assets *@ 105 var selectedAssetCategories = Model.Item.GetRawValueString("ImageAssets").Split(',').ToList(); 106 bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages"); 107 108 @* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@ 109 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 110 IEnumerable<MediaViewModel> assetsImages = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 111 assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage)); 112 IEnumerable<MediaViewModel> assetsList = new MediaViewModel[]{}; 113 assetsList = assetsList.Union(assetsImages); 114 assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList; 115 assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList; 116 117 bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback"); 118 119 int totalAssets = 0; 120 foreach (MediaViewModel asset in assetsList) { 121 var assetValue = asset.Value; 122 foreach (string format in allSupportedFormats) { 123 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 124 totalAssets++; 125 } 126 } 127 } 128 129 if (totalAssets == 0) 130 { 131 if (defaultImageFallback) { 132 assetsList = new List<MediaViewModel>(){ product.DefaultImage }; 133 totalAssets = 1; 134 } else { 135 assetsList = new List<MediaViewModel>(){ }; 136 totalAssets = 0; 137 } 138 } 139 140 @* Layout settings *@ 141 string spacing = Model.Item.GetRawValueString("Spacing", "4"); 142 spacing = spacing == "none" ? "gap-0" : spacing; 143 spacing = spacing == "small" ? "gap-3" : spacing; 144 spacing = spacing == "large" ? "gap-4" : spacing; 145 146 galleryLayout = Model.Item.GetRawValueString("Layout", "grid"); 147 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 148 149 var badgeParms = new Dictionary<string, object>(); 150 badgeParms.Add("size", "h5"); 151 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 152 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 153 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 154 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 155 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 156 157 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 158 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 159 DateTime createdDate = product.Created.Value; 160 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 161 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 162 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 163 164 165 @* Get assets from selected categories or get all assets *@ 166 if (totalAssets != 0 && assetsList.Count() != 0) { 167 int desktopAssetNumber = 0; 168 int mobileAssetNumber = 0; 169 int mobileAssetThumbnailNumber = 0; 170 int modalAssetNumber = 0; 171 172 @* Desktop: Show the gallery on large screens *@ 173 <div class="d-none d-lg-block h-100 position-relative @theme item_@Model.Item.SystemName.ToLower() desktop"> 174 <div class="grid @spacing"> 175 @foreach (MediaViewModel asset in assetsList) { 176 var assetName = asset.Value; 177 foreach (string format in allSupportedFormats) { 178 if (assetName.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 179 string size = "desktop"; 180 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 181 string assetValue = asset.Value; 182 183 <div class="@GetColumnClass(totalAssets, desktopAssetNumber)"> 184 <div class="h-100 @(imageTheme)"> 185 @foreach (string imageFormat in supportedImageFormats) 186 { //Images 187 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) 188 { 189 string productName = product.Name; 190 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 191 string imageLinkPath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 192 193 RatioSettings ratioSettings = GetRatioSettings(size); 194 195 var parms = new Dictionary<string, object>(); 196 parms.Add("alt", productName); 197 parms.Add("itemprop", "image"); 198 if (totalAssets > 1) 199 { 200 parms.Add("columns", 2); 201 } 202 else 203 { 204 parms.Add("columns", 1); 205 } 206 parms.Add("eagerLoadNewImages", Model.Item.GetBoolean("DisableLazyLoading")); 207 parms.Add("doNotUseGetimage", Model.Item.GetBoolean("DisableGetImage")); 208 209 if (!string.IsNullOrEmpty(asset.DisplayName)) 210 { 211 parms.Add("title", asset.DisplayName); 212 } 213 214 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 215 { 216 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 217 } 218 else 219 { 220 parms.Add("cssClass", "mw-100 mh-100"); 221 } 222 223 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 224 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@desktopAssetNumber"> 225 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 226 </div> 227 </a> 228 } 229 } 230 @foreach (string videoFormat in supportedVideoFormats) 231 { //Videos 232 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 233 { 234 if (Model.Item.GetString("OpenVideoInModal") == "true") 235 { 236 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 237 238 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 239 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 240 videoScreendumpPath = videoScreendumpPath.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || videoScreendumpPath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) != 0 ? "https://img.youtube.com/vi/" + videoId + "/maxresdefault.jpg" : videoScreendumpPath; 241 242 string vimeoJsClass = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 243 videoScreendumpPath = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "" : videoScreendumpPath; 244 245 string productName = product.Name; 246 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 247 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 248 249 RatioSettings ratioSettings = GetRatioSettings(size); 250 251 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 252 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@desktopAssetNumber"> 253 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 254 @if (videoScreendumpPath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) 255 { 256 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@vimeoJsClass mw-100 mh-100" data-video-id="@videoId" style="object-fit: cover;" onload="CheckIfVideoThumbnailExist(this)"> 257 } 258 else 259 { 260 string videoType = Path.GetExtension(asset.Value).ToLower(); 261 string videoPathEncoded = System.Uri.EscapeDataString(assetValue); 262 263 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 264 <source src="@(videoPathEncoded)#t=0.001" type="video/@videoType.Replace(".", "")"> 265 </video> 266 } 267 </div> 268 </div> 269 270 <script> 271 function CheckIfVideoThumbnailExist(image) { 272 if (image.width == 120) { 273 const lowQualityImage = "https://img.youtube.com/vi/@(videoId)/hqdefault.jpg" 274 image.src = lowQualityImage; 275 } 276 } 277 </script> 278 } 279 else 280 { 281 Dictionary<string, object> videoParams = GetVideoParams(asset, size); 282 @RenderPartial("Components/VideoPlayer.cshtml", new FileViewModel { Path = asset.Value }, videoParams); 283 } 284 } 285 } 286 @foreach (string documentFormat in supportedDocumentFormats) 287 { //Documents 288 if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0) 289 { 290 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 291 292 string productName = product.Name; 293 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 294 string imageLinkPath = imagePath; 295 296 RatioSettings ratioSettings = GetRatioSettings(size); 297 298 var parms = new Dictionary<string, object>(); 299 parms.Add("alt", productName); 300 parms.Add("itemprop", "image"); 301 parms.Add("fullwidth", true); 302 parms.Add("columns", Model.GridRowColumnCount); 303 if (!string.IsNullOrEmpty(asset.DisplayName)) 304 { 305 parms.Add("title", asset.DisplayName); 306 } 307 308 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 309 { 310 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 311 } 312 else 313 { 314 parms.Add("cssClass", "mw-100 mh-100"); 315 } 316 317 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download title="@Translate("Download")"> 318 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 319 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 320 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) 321 { 322 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 323 } 324 else 325 { 326 327 } 328 </div> 329 </a> 330 } 331 } 332 </div> 333 </div> 334 desktopAssetNumber++; 335 } 336 } 337 } 338 </div> 339 340 @if (showBadges) { 341 <div class="position-absolute top-0 left-0 p-2 p-lg-3 w-100"> 342 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 343 </div> 344 } 345 </div> 346 347 @* Mobile: Show the thumbs on small screens *@ 348 <div class="d-block d-lg-none mx-lg-0 position-relative @theme item_@Model.Item.SystemName.ToLower() mobile"> 349 <div id="SmallScreenImages_@Model.ID" class="carousel@(GetArrowsColor())" data-bs-ride="carousel"> 350 <div class="carousel-inner h-100"> 351 @foreach (MediaViewModel asset in assetsList) { 352 var assetValue = asset.Value; 353 foreach (string format in allSupportedFormats) { 354 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 355 string activeSlide = mobileAssetNumber == 0 ? "active" : ""; 356 string size = "mobile"; 357 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 358 359 <div class="carousel-item @activeSlide" data-bs-interval="99999"> 360 <div class="h-100 @(imageTheme)"> 361 @foreach (string supportedFormat in supportedImageFormats) 362 { //Images 363 if (assetValue.IndexOf(supportedFormat, StringComparison.OrdinalIgnoreCase) >= 0) 364 { 365 string productName = product.Name; 366 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 367 string imageLinkPath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 368 369 RatioSettings ratioSettings = GetRatioSettings(size); 370 371 var parms = new Dictionary<string, object>(); 372 parms.Add("alt", productName); 373 parms.Add("itemprop", "image"); 374 if (totalAssets > 1) 375 { 376 parms.Add("columns", 2); 377 } 378 else 379 { 380 parms.Add("columns", 1); 381 } 382 parms.Add("eagerLoadNewImages", Model.Item.GetBoolean("DisableLazyLoading")); 383 parms.Add("doNotUseGetimage", Model.Item.GetBoolean("DisableGetImage")); 384 385 if (!string.IsNullOrEmpty(asset.DisplayName)) 386 { 387 parms.Add("title", asset.DisplayName); 388 } 389 390 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 391 { 392 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 393 } 394 else 395 { 396 parms.Add("cssClass", "mw-100 mh-100"); 397 } 398 399 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 400 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@desktopAssetNumber"> 401 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 402 </div> 403 </a> 404 } 405 } 406 @foreach (string videoFormat in supportedVideoFormats) 407 { //Videos 408 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 409 { 410 if (Model.Item.GetString("OpenVideoInModal") == "true") 411 { 412 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 413 414 string videoScreendumpPath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : ""; 415 string videoId = videoScreendumpPath.Substring(videoScreendumpPath.LastIndexOf('/') + 1); 416 videoScreendumpPath = videoScreendumpPath.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || videoScreendumpPath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) != 0 ? "https://img.youtube.com/vi/" + videoId + "/maxresdefault.jpg" : videoScreendumpPath; 417 418 string vimeoJsClass = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 419 videoScreendumpPath = videoScreendumpPath.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "" : videoScreendumpPath; 420 421 string productName = product.Name; 422 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 423 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 424 425 RatioSettings ratioSettings = GetRatioSettings(size); 426 427 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID"> 428 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@desktopAssetNumber"> 429 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 430 @if (videoScreendumpPath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) 431 { 432 <img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@vimeoJsClass mw-100 mh-100" data-video-id="@videoId" style="object-fit: cover;" onload="CheckIfVideoThumbnailExist(this)"> 433 } 434 else 435 { 436 string videoType = Path.GetExtension(asset.Value).ToLower(); 437 string videoPathEncoded = System.Uri.EscapeDataString(asset.Value); 438 439 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 440 <source src="@(videoPathEncoded)#t=0.001" type="video/@videoType.Replace(".", "")"> 441 </video> 442 } 443 </div> 444 </div> 445 446 <script> 447 function CheckIfVideoThumbnailExist(image) { 448 if (image.width == 120) { 449 const lowQualityImage = "https://img.youtube.com/vi/@(videoId)/hqdefault.jpg" 450 image.src = lowQualityImage; 451 } 452 } 453 </script> 454 } 455 else 456 { 457 Dictionary<string, object> videoParams = GetVideoParams(asset, size); 458 @RenderPartial("Components/VideoPlayer.cshtml", new FileViewModel { Path = asset.Value }, videoParams); 459 } 460 } 461 } 462 @foreach (string documentFormat in supportedDocumentFormats) 463 { //Documents 464 if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0) 465 { 466 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 467 468 string productName = product.Name; 469 string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 470 string imageLinkPath = imagePath; 471 472 RatioSettings ratioSettings = GetRatioSettings(size); 473 474 var parms = new Dictionary<string, object>(); 475 parms.Add("alt", productName); 476 parms.Add("itemprop", "image"); 477 parms.Add("fullwidth", true); 478 parms.Add("columns", Model.GridRowColumnCount); 479 if (!string.IsNullOrEmpty(asset.DisplayName)) 480 { 481 parms.Add("title", asset.DisplayName); 482 } 483 484 if (ratioSettings.Ratio == "fill" && galleryLayout != "grid") 485 { 486 parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover"); 487 } 488 else 489 { 490 parms.Add("cssClass", "mw-100 mh-100"); 491 } 492 493 <a href="@imageLinkPath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download title="@Translate("Download")"> 494 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 495 <div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "download.svg")</div> 496 @if (asset.Value.IndexOf(".pdf", StringComparison.OrdinalIgnoreCase) >= 0) 497 { 498 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 499 } 500 else 501 { 502 503 } 504 </div> 505 </a> 506 } 507 } 508 </div> 509 </div> 510 mobileAssetNumber++; 511 } 512 } 513 } 514 </div> 515 </div> 516 517 @if (totalAssets > 1) { 518 <div id="SmallScreenImagesThumbnails_@Model.ID" class="d-flex flex-nowrap gap-2 overflow-x-auto my-3"> 519 @foreach (MediaViewModel asset in assetsList) { 520 var assetValue = asset.Value; 521 foreach (string format in allSupportedFormats) { 522 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 523 string imagePath = Dynamicweb.Context.Current.Server.UrlEncode(assetValue); 524 imagePath = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + assetValue.Substring(assetValue.LastIndexOf('/') + 1) + "/default.jpg" : imagePath; 525 string imagePathThumb = assetValue.StartsWith("/Files/", StringComparison.OrdinalIgnoreCase) ? imagePath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) < 0 ? $"/Admin/Public/GetImage.ashx?image={imagePath}&width=160&format=webp" : imagePath : assetValue; 526 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 527 528 string videoId = assetValue.Substring(assetValue.LastIndexOf('/') + 1); 529 string vimeoJsClass = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "js-vimeo-video-thumbnail" : ""; 530 531 string productName = product.Name; 532 productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : ""; 533 string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : ""; 534 535 <div class="ratio ratio-4x3 border outline-none" style="flex:0 0 80px" data-bs-target="#SmallScreenImages_@Model.ID" data-bs-slide-to="@mobileAssetThumbnailNumber"> 536 537 @foreach (string videoFormat in supportedVideoFormats) 538 { 539 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) 540 { 541 <div class="d-flex align-items-center justify-content-center overflow-hidden h-100"> 542 <div class="icon-3 position-absolute text-light" style="z-index: 1">@ReadFile(iconPath+"play-circle.svg")</div> 543 </div> 544 } 545 } 546 @if (imagePathThumb.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0) 547 { 548 549 <img src="@(imagePathThumb)" class="p-1 @vimeoJsClass mw-100 mh-100" data-video-id="@videoId" style="object-fit: contain;" alt="@productName" @assetTitle> 550 551 } 552 else 553 { 554 string videoType = Path.GetExtension(asset.Value).ToLower(); 555 string videoPathEncoded = System.Uri.EscapeDataString(assetValue); 556 557 <video preload="auto" class="h-100 w-100" style="object-fit: contain;"> 558 <source src="@(videoPathEncoded)#t=0.001" type="video/@videoType.Replace(".", "")"> 559 </video> 560 } 561 562 </div> 563 564 mobileAssetThumbnailNumber++; 565 } 566 } 567 } 568 </div> 569 } 570 571 @if (showBadges) { 572 <div class="position-absolute top-0 left-0 p-2 p-lg-3"> 573 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 574 </div> 575 } 576 </div> 577 578 @* Modal with slides *@ 579 <div class="modal fade swift_products-details-images-modal" id="modal_@Model.ID" tabindex="-1" aria-labelledby="productDetailsGalleryModalTitle_@Model.ID" aria-hidden="true"> 580 <div class="modal-dialog modal-dialog-centered modal-xl"> 581 <div class="modal-content"> 582 <div class="modal-header visually-hidden"> 583 <h5 class="modal-title" id="productDetailsGalleryModalTitle_@Model.ID">@product.Title</h5> 584 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 585 </div> 586 <div class="modal-body p-2 p-lg-3 h-100"> 587 <div id="ModalCarousel_@Model.ID" class="carousel@(GetArrowsColor()) h-100" data-bs-ride="carousel"> 588 <div class="carousel-inner h-100 @theme"> 589 @foreach (MediaViewModel asset in assetsList) { 590 var assetValue = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value; 591 foreach (string format in allSupportedFormats) { 592 if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0) { 593 string imagePath = assetValue; 594 string activeSlide = modalAssetNumber == 0 ? "active" : ""; 595 596 var parms = new Dictionary<string, object>(); 597 parms.Add("cssClass", "d-block mw-100 mh-100 m-auto"); 598 parms.Add("columns", Model.GridRowColumnCount); 599 parms.Add("eagerLoadNewImages", Model.Item.GetBoolean("DisableLazyLoading")); 600 parms.Add("doNotUseGetimage", Model.Item.GetBoolean("DisableGetImage")); 601 602 <div class="carousel-item @activeSlide h-100" data-bs-interval="99999"> 603 @foreach (string imageFormat in supportedImageFormats) { 604 if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 605 @RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms) 606 } 607 } 608 609 @foreach (string videoFormat in supportedVideoFormats) { 610 if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0) { 611 612 Dictionary<string, object> videoParams = GetVideoParams(asset, "modal"); 613 @RenderPartial("Components/VideoPlayer.cshtml", new FileViewModel { Path = asset.Value }, videoParams); 614 615 } 616 } 617 </div> 618 619 modalAssetNumber++; 620 } 621 } 622 } 623 <button class="carousel-control-prev" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="prev"> 624 <span class="carousel-control-prev-icon" aria-hidden="true"></span> 625 <span class="visually-hidden">@Translate("Previous")</span> 626 </button> 627 <button class="carousel-control-next" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="next"> 628 <span class="carousel-control-next-icon" aria-hidden="true"></span> 629 <span class="visually-hidden">@Translate("Next")</span> 630 </button> 631 </div> 632 </div> 633 </div> 634 </div> 635 </div> 636 </div> 637 } else if (Pageview.IsVisualEditorMode) { 638 RatioSettings ratioSettings = GetRatioSettings("desktop"); 639 640 <div class="h-100 @theme"> 641 <div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)"> 642 <img src="/Files/Images/missing_image.jpg" loading="lazy" decoding="async" class="mh-100 mw-100" style="object-fit: cover;" alt="@Translate("Missing image")"> 643 </div> 644 </div> 645 } 646 } 647
California residents see: Proposition 65 WARNING