Sort by

Color

Error executing template "Designs/Swift/Paragraph/Swift_ProductListGridView.cshtml"
System.InvalidOperationException: ValueFactory attempted to access the Value property of this instance.
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.VariantInfoViewModel.CalculatePrice()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Dynamicweb.Ecommerce.ProductCatalog.VariantInfoViewModel.CalculatePriceMin()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at CompiledRazorTemplates.Dynamic.RazorEngine_65a057f947704223903cd08aff1a62f7.<RenderProductList>b__7_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Zington\ote.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListGridView.cshtml:line 349
   at CompiledRazorTemplates.Dynamic.RazorEngine_65a057f947704223903cd08aff1a62f7.Execute() in D:\dynamicweb.net\Solutions\Zington\ote.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListGridView.cshtml:line 58
   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.Ecommerce.CustomerExperienceCenter.Favorites 4 @using System.Linq 5 @using Dynamicweb.Core 6 @using Dynamicweb.Environment 7 8 @functions 9 { 10 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsLazyLoadingForProductInfoEnabled"]); 11 string liveInfoClass = ""; 12 string productInfoFeed = ""; 13 14 string showPricesWithVat = ""; 15 bool neverShowVat = false; 16 17 bool isDetailPage = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")); 18 19 ProductListViewModel productList = new ProductListViewModel(); 20 } 21 22 @{ 23 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 24 { 25 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 26 } 27 28 showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 29 neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 30 31 if (isLazyLoadingForProductInfoEnabled) 32 { 33 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) 34 { 35 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 36 if (!string.IsNullOrEmpty(productInfoFeed)) 37 { 38 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 39 } 40 } 41 liveInfoClass = "js-live-info"; 42 } 43 44 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 45 string themePadding = theme != string.Empty ? "p-3" : string.Empty; 46 } 47 48 @if (!isDetailPage) { 49 if (!string.IsNullOrEmpty(theme)) 50 { 51 <div class="h-100@(theme) @themePadding item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 52 @{@RenderProductList()} 53 </div> 54 } 55 else 56 { 57 <div class="pt-3 item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 58 @{@RenderProductList()} 59 </div> 60 } 61 } 62 63 @helper RenderProductList() 64 { 65 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 66 bool anonymousUser = Pageview.User == null; 67 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]); 68 69 string productTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ProductTheme")) ? " theme " + Model.Item.GetRawValueString("ProductTheme").Replace(" ", "").Trim().ToLower() : ""; 70 string productThemePadding = productTheme != string.Empty ? "p-3" : string.Empty; 71 72 string url = Dynamicweb.Context.Current.Request.RawUrl; 73 bool hideFavoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("HideFavoritesSelector")) ? Model.Item.GetBoolean("HideFavoritesSelector") : false; 74 string staticVariantsLayout = Model.Item.GetRawValueString("StaticVariantsLayout", "hide"); 75 76 string groupId = productList?.Group?.Id != null ? productList.Group.Id : ""; 77 78 var badgeParms = new Dictionary<string, object>(); 79 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 80 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 81 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 82 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 83 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 84 85 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 86 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 87 88 string googleTagManagerID = Pageview.AreaSettings.GetString("GoogleTagManagerID"); 89 string googleAnalyticsMeasurementID = Pageview.AreaSettings.GetString("GoogleAnalyticsMeasurementID"); 90 var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); 91 bool allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical")); 92 93 var favoriteParameters = new Dictionary<string, object>(); 94 if (!anonymousUser && !hideFavoritesSelector) 95 { 96 int defaultFavoriteListId = 0; 97 98 IEnumerable<FavoriteList> favoreiteLists = Pageview.User.GetFavoriteLists(); 99 if (favoreiteLists.Count() == 1) { 100 foreach (FavoriteList list in favoreiteLists) { 101 defaultFavoriteListId = list.ListId; 102 } 103 } 104 105 favoriteParameters.Add("ListId", defaultFavoriteListId); 106 } 107 108 if (productList.TotalProductsCount > 0) 109 { 110 int pageSizeSetting = 30; 111 int pageSize = productList.PageSize; 112 pageSize += pageSizeSetting; 113 114 int loadedProducts = productList.PageSize > productList.TotalProductsCount ? productList.TotalProductsCount : productList.PageSize; 115 116 <div class="grid grid-2 grid-lg-3"> 117 118 @if ((!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) || !string.IsNullOrWhiteSpace(googleTagManagerID)) && allowTracking) 119 { 120 <script> 121 gtag("event", "view_item_list", { 122 item_list_id: "product_list_gridview", 123 item_list_name: "Product list (Gridview)", 124 items: [ 125 @foreach (ProductViewModel product in productList.Products) 126 { 127 <text>{ 128 item_id: "@product.Number", 129 item_name: "@Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(product.Name)", 130 currency: "@product.Price.CurrencyCode", 131 price: @PriceViewModelExtensions.ToStringInvariant(product.Price) 132 },</text> 133 } 134 ] 135 }); 136 </script> 137 } 138 139 @foreach (ProductViewModel product in productList.Products) 140 { 141 string link = product.GetProductLink(GetPageIdByNavigationTag("Shop"), false); 142 143 string imagePath = product?.DefaultImage?.Value ?? ""; 144 imagePath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 145 146 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 147 ratio = ratio != "0" ? ratio : ""; 148 string ratioCssClass = ratio != "" ? " ratio" : ""; 149 string ratioVariable = ratio != "" ? "--bs-aspect-ratio: " + ratio : ""; 150 151 string imagePathXs = "/Admin/Public/GetImage.ashx?width=" + 480 + "&image=" + imagePath + "&format=webp"; 152 string imagePathS = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 153 string imagePathFallBack = "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + imagePath + "&format=webp"; 154 155 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 156 string imageThemePadding = imageTheme != string.Empty ? "p-3" : string.Empty; 157 string imageOutlineStyle = imageTheme == string.Empty ? "style=\"border: 1px solid transparent\"" : string.Empty; 158 159 string imageId = "ProductImage_" + product.Id + product.VariantId; 160 string priceId = "ProductPrice_" + product.Id + product.VariantId; 161 162 @* Alternative image *@ 163 var supportedImageFormats = new string[] { ".jpg", ".webp", ".png", ".gif" }; 164 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 165 var selectedAssetCategories = Model.Item.GetRawValueString("AlternativeImageAssets"); 166 IEnumerable<MediaViewModel> alternativeImagesList = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 167 168 if (alternativeImagesList.FirstOrDefault() != null) 169 { 170 alternativeImagesList = alternativeImagesList.OrderByDescending(x => x.Value.Equals(defaultImage)); 171 172 if (alternativeImagesList.First().Value == defaultImage) { 173 alternativeImagesList = alternativeImagesList.Skip(1); 174 } 175 } 176 177 string alternativeImage = alternativeImagesList.FirstOrDefault() != null ? alternativeImagesList.FirstOrDefault().Value : ""; 178 alternativeImage = !string.IsNullOrEmpty(alternativeImage) ? "/Admin/Public/GetImage.ashx?width=" + 640 + "&image=" + alternativeImage + "&format=webp" : ""; 179 180 @* Badges *@ 181 DateTime createdDate = product.Created.Value; 182 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 183 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 184 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 185 186 @* Main features *@ 187 IEnumerable<string> selectedDisplayGroups = Model.Item.GetRawValueString("MainFeatures").Split(',').ToList(); 188 List<CategoryFieldViewModel> mainFeatures = new List<CategoryFieldViewModel>(); 189 190 foreach (var selection in selectedDisplayGroups) 191 { 192 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) 193 { 194 if (selection == group.Id) { 195 mainFeatures.Add(group); 196 } 197 } 198 } 199 200 <article class="position-relative@(productTheme) product-list-item js-product @liveInfoClass" data-product-id="@product.Id" data-variant-id="@product.VariantId" itemscope itemtype="https://schema.org/Product"> 201 @if (!anonymousUser) { 202 if (!hideFavoritesSelector) 203 { 204 <div class="position-absolute top-0 end-0 my-3" style="z-index: 2"> 205 @RenderPartial("Components/ToggleFavorite.cshtml", product, favoriteParameters) 206 </div> 207 } 208 } 209 210 @if (showBadges) { 211 <div class="position-absolute top-0 left-0 p-1 p-lg-2 ps-0 ps-lg-0" style="z-index: 2"> 212 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 213 </div> 214 } 215 216 <div class="d-flex flex-column d-block h-100"> 217 @{ 218 string clickProductLink = string.Empty; 219 if ((!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) || !string.IsNullOrWhiteSpace(googleTagManagerID)) && allowTracking) 220 { 221 clickProductLink = "onclick=\"return clickProductLink('" + @product.Id + "', '" + @Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(product.Name) + "', '" + @Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(product.VariantName) + "', '" + @product.Price.CurrencyCode + "', '" + @PriceViewModelExtensions.ToStringInvariant(product.Price) + "')\""; 222 } 223 } 224 <a href="/@link" class="text-decoration-none d-flex flex-column" @clickProductLink> 225 @if ((!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) || !string.IsNullOrWhiteSpace(googleTagManagerID)) && allowTracking) 226 { 227 <script> 228 function clickProductLink(productId, productName, productVariant, productCurrency, productPrice) { 229 if (typeof gtag !== "undefined") { 230 gtag("event", "select_item", { 231 item_list_id: "product_list_gridview", 232 item_list_name: "Product list (Gridview)", 233 items: [ 234 { 235 item_id: productId, 236 item_name: productName, 237 currency: productCurrency, 238 item_list_id: "product_list_gridview", 239 item_list_name: "Product list (Gridview)", 240 item_variant: productVariant, 241 price: productPrice 242 } 243 ] 244 }); 245 } 246 } 247 </script> 248 } 249 250 <div class="@productThemePadding order-2"> 251 <div class="flex-grow-1"> 252 <h3 class="h6 mb-0 text-break">@product.Name @if (!string.IsNullOrEmpty(product.VariantName)) { <text>(@product.VariantName)</text> }</h3> 253 @if (!Model.Item.GetBoolean("HideProductNumber")) { 254 <p class="fs-7 opacity-85 mb-2">@product.Number</p> 255 } 256 @if (mainFeatures.Count > 0) 257 { 258 <ul class="p-0 lh-sm opacity-75" style="list-style-position: inside"> 259 @foreach (CategoryFieldViewModel mainFeatureGroup in mainFeatures) 260 { 261 foreach (var fieldViewModel in mainFeatureGroup.Fields) 262 { 263 var field = fieldViewModel.Value; 264 string fieldValue = field?.Value is object ? field.Value.ToString() : ""; 265 266 if (fieldValue != "") { 267 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 268 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 269 270 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) { 271 fieldValue = ""; 272 273 foreach (FieldOptionValueViewModel option in field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) { 274 fieldValue = option.Name; 275 } 276 } 277 278 bool isColor = false; 279 if (fieldValue.Contains("#") && (Translate(field.Name) == Translate("Color") || Translate(field.Name) == Translate("Colour"))) { 280 isColor = true; 281 } 282 283 if (!string.IsNullOrEmpty(fieldValue)) { 284 if (!isColor) { 285 <li>@(field.Name): @fieldValue</li> 286 } else { 287 <li class="position-relative"> 288 <span class="colorbox-sm" style="background-color: @fieldValue"></span> 289 </li> 290 } 291 } 292 } 293 } 294 } 295 </ul> 296 } 297 </div> 298 299 @if (!hidePrice) { 300 string priceMin = ""; 301 string priceMax = ""; 302 303 <div> 304 <div> 305 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 306 307 @if (showPricesWithVat == "false" && !neverShowVat) { 308 if (isLazyLoadingForProductInfoEnabled) 309 { 310 <span itemprop="price" content="" class="d-none"></span> 311 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 312 } 313 else 314 { 315 string beforePrice = product.PriceBeforeDiscount.PriceWithoutVatFormatted; 316 <span itemprop="price" content="@product.Price.PriceWithoutVat" class="d-none"></span> 317 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 318 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 319 } 320 } 321 322 } else { 323 324 if (isLazyLoadingForProductInfoEnabled) 325 { 326 <span itemprop="price" content="" class="d-none"></span> 327 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 328 } 329 else 330 { 331 string beforePrice = product.PriceBeforeDiscount.PriceFormatted; 332 333 <span itemprop="price" content="@product.Price.Price" class="d-none"></span> 334 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 335 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 336 } 337 } 338 } 339 340 @if (showPricesWithVat == "false" && !neverShowVat) { 341 if (isLazyLoadingForProductInfoEnabled) 342 { 343 <span class="text-price js-text-price"><span class="spinner-border" role="status"></span></span> 344 } 345 else 346 { 347 string price = product.Price.PriceWithoutVatFormatted; 348 if (product?.VariantInfo?.VariantInfo != null) { 349 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVatFormatted : ""; 350 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVatFormatted : ""; 351 } 352 if (priceMin != priceMax) { 353 price = priceMin + " - " + priceMax; 354 } 355 <span class="text-price">@price</span> 356 } 357 } else { 358 if (isLazyLoadingForProductInfoEnabled) 359 { 360 <span class="text-price js-text-price"><span class="spinner-border" role="status"></span></span> 361 } 362 else 363 { 364 string price = product.Price.PriceFormatted; 365 if (product?.VariantInfo?.VariantInfo != null) { 366 priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? product.VariantInfo.PriceMin.PriceFormatted : ""; 367 priceMax = product?.VariantInfo?.PriceMax?.PriceFormatted != null ? product.VariantInfo.PriceMax.PriceFormatted : ""; 368 } 369 if (priceMin != priceMax) { 370 price = priceMin + " - " + priceMax; 371 } 372 <span class="text-price">@price</span> 373 } 374 } 375 </div> 376 @if (showPricesWithVat == "false" && !neverShowVat) { 377 if (isLazyLoadingForProductInfoEnabled) 378 { 379 <div class="fs-7 opacity-85 text-price js-text-price-with-vat d-none" data-suffix="@Translate("Incl. VAT")"></div> 380 } 381 else 382 { 383 string price = product.Price.PriceWithVatFormatted; 384 if (product?.VariantInfo?.VariantInfo != null) { 385 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : ""; 386 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : ""; 387 } 388 if (priceMin != priceMax) { 389 price = priceMin + " - " + priceMax; 390 } 391 <div class="fs-7 opacity-85 text-price">@price @Translate("Incl. VAT")</div> 392 } 393 } 394 </div> 395 } 396 397 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "swatches") { 398 var optionCount = product.VariantInfo.VariantInfo.Count(); 399 var showMaxVariants = 5; 400 401 <div class="d-flex flex-row gap-1 align-items-center"> 402 @foreach (VariantInfoViewModel variant in product.VariantInfo.VariantInfo.Take(showMaxVariants)) 403 { 404 <span class="colorbox colorbox-sm rounded-circle border me-1" style="background-color: @variant.OptionColor"></span> 405 } 406 @if (optionCount > showMaxVariants) 407 { 408 int left = optionCount - showMaxVariants; 409 <span class="ms-2">+@left</span> 410 } 411 </div> 412 } 413 </div> 414 415 <div class="overflow-hidden order-1 @(imageTheme)" @imageOutlineStyle> 416 <div class="ratio" style="@(ratioVariable)"> 417 <div class="d-flex justify-content-center align-items-center"> 418 @if (string.IsNullOrEmpty(alternativeImage)) { 419 <img 420 id="@imageId" 421 srcset=" 422 @imagePathXs 480w, 423 @imagePathS 640w" 424 sizes="(min-width: 992px) 33vw, 50vw" 425 src="@imagePathFallBack" 426 loading="lazy" 427 decoding="async" 428 class="mw-100 mh-100 @imageThemePadding" 429 alt="@product.Name"> 430 } else { 431 <img 432 id="@imageId" 433 src="@imagePathFallBack" 434 loading="lazy" 435 decoding="async" 436 class="mw-100 mh-100 @imageThemePadding" 437 alt="@product.Name" 438 onmouseover="this.src='@alternativeImage'" 439 onmouseout="this.src='@imagePathFallBack'"> 440 } 441 </div> 442 </div> 443 444 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "images") 445 { 446 int variantGroupCount = 0; 447 int showMaxVariantGroups = 2; 448 int showMaxVariants = 3; 449 var productVariantTheme = productTheme != "" ? productTheme : "bg-white"; 450 451 <div class="position-relative"> 452 <div id="StaticVariants_@product.Id" class="static-variants w-100 d-none d-lg-block position-absolute left-0 bottom-0 @productTheme" style="pointer-events: none;"> 453 454 @foreach (var variantGroup in product.VariantGroups()) 455 { 456 int variantsCount = 0; 457 458 <div class="d-flex gap-2 mb-2"> 459 @foreach (var variant in variantGroup.Options) 460 { 461 if (variantGroupCount < showMaxVariantGroups) 462 { 463 var optionsCount = variantGroup.Options.Count(); 464 465 if (variantsCount < showMaxVariants) 466 { 467 string optionWidth = !string.IsNullOrEmpty(variant.Color) ? "w-25" : ""; 468 469 <article class="static-variants-option @optionWidth @(productVariantTheme)" title="@product.Name @variant.Name" style="pointer-events: initial;"> 470 @if (!string.IsNullOrEmpty(variant.Color)) 471 { 472 string defaultProductImage = Dynamicweb.Context.Current.Server.UrlEncode(product.DefaultImage.Value); 473 string variantImage = Dynamicweb.Context.Current.Server.UrlEncode(variant.Image.Value); 474 string defaultPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 475 string variantPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 476 477 if (isLazyLoadingForProductInfoEnabled) 478 { 479 <figure class="w-100 d-block m-0" data-price-formatted="" onmouseover="swift.StaticVariants.SwitchProduct(event, '@product.Id', this.getAttribute('data-price-formatted'), '@variant.Image.Value')" onmouseout="swift.StaticVariants.SwitchProduct(event, '@product.Id', this.getAttribute('data-price-formatted'), '@product.DefaultImage.Value)')"> 480 <div class="d-flex align-items-center justify-content-center"> 481 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 482 </div> 483 </figure> 484 } 485 else 486 { 487 <figure class="w-100 d-block m-0" onmouseover="swift.StaticVariants.SwitchProduct(event, '@product.Id', '@defaultPrice', '@variant.Image.Value')" onmouseout="swift.StaticVariants.SwitchProduct(event, '@product.Id', '@variantPrice', '@product.DefaultImage.Value')"> 488 <div class="d-flex align-items-center justify-content-center"> 489 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 490 </div> 491 </figure> 492 } 493 } 494 else 495 { 496 <div class="d-flex align-items-center justify-content-center"> 497 @variant.Name 498 </div> 499 } 500 <div class="visually-hidden"> 501 <h4>@product.Name, @variant.Name</h4> 502 @if (!hidePrice) { 503 if (isLazyLoadingForProductInfoEnabled) 504 { 505 <span class="text-price js-text-price"></span> 506 } 507 else 508 { 509 <span class="text-price">@product.Price.PriceFormatted</span> 510 } 511 } 512 </div> 513 </article> 514 } 515 516 variantsCount++; 517 518 if (variantsCount == showMaxVariants && optionsCount != showMaxVariants) 519 { 520 int left = optionsCount - showMaxVariants; 521 <div class="variant-option ms-1 d-flex justify-content-center align-items-center"> 522 <span>+@left</span> 523 </div> 524 } 525 } 526 } 527 </div> 528 529 variantGroupCount++; 530 } 531 </div> 532 </div> 533 } 534 </div> 535 </a> 536 </div> 537 </article> 538 } 539 </div> 540 541 <div class="my-3" id="LoadMoreButton"> 542 <div class="text-center d-flex flex-column gap-3"> 543 <div class="opacity-85">@loadedProducts @Translate("out of") @productList.TotalProductsCount @Translate("products")</div> 544 @if (productList.PageCount != 1) { 545 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 546 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 547 string mainProductId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("MainProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("MainProductID") : ""; 548 549 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 550 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 551 552 <form method="get" action="@url" data-response-target-element="content" class="w-100"> 553 @foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 554 { 555 foreach (FacetViewModel facetItem in facetGroup.Facets) 556 { 557 foreach (FacetOptionViewModel facetOption in facetItem.Options) 558 { 559 if (facetOption.Selected) 560 { 561 <input type="hidden" name="@facetItem.QueryParameter" value="[@facetOption.Value]"> 562 } 563 } 564 } 565 } 566 567 <input type="hidden" name="PageSize" value="@pageSize"> 568 <input type="hidden" name="SortBy" value="@sortBySelection"> 569 <input type="hidden" name="RequestType" value="UpdateList"> 570 571 @if (!string.IsNullOrEmpty(searchQuery)) 572 { 573 <input type="hidden" name="q" value="@searchQuery"> 574 <input type="hidden" name="SearchLayout" value="@searchLayout"> 575 } 576 577 @if (!string.IsNullOrEmpty(mainProductId)) 578 { 579 <input type="hidden" name="MainProductID" value="@mainProductId"> 580 } 581 582 @{ 583 string nextPageLink = "/Default.aspx?ID=" + Pageview.Page.ID + "&PageSize=" + pageSize + "&SortBy=" + sortBySelection; 584 585 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 586 { 587 foreach (FacetViewModel facetItem in facetGroup.Facets) 588 { 589 foreach (FacetOptionViewModel facetOption in facetItem.Options) 590 { 591 if (facetOption.Selected) 592 { 593 nextPageLink += "&" + facetItem.QueryParameter + "=[" + facetOption.Value + "]"; 594 } 595 } 596 } 597 } 598 599 nextPageLink += !string.IsNullOrEmpty(searchQuery) ? "&q=" + searchQuery : ""; 600 } 601 602 <a href="@nextPageLink" class="btn btn-primary" onclick="swift.ProductList.Update(event)" id="LoadMoreButton_@Model.ID">@Translate("Load more products")</a> 603 </form> 604 } 605 </div> 606 </div> 607 } else { 608 if (!Pageview.IsVisualEditorMode) { 609 <div class="alert alert-dark m-0"> 610 @Translate("We did not find anything matching your search result") 611 </div> 612 } else { 613 <div class="alert alert-dark m-0" role="alert"> 614 <span>@Translate("Product list: The list will be shown here, if any")</span> 615 </div> 616 } 617 } 618 } 619
By clicking 'Accept All' you consent that we may collect information about you for various purposes, including: Functionality, Statistics and Marketing