0
Din indkøbskurv

Opdaterer kurv

stk. a

-
+

Din kurv i alt (ex. fragt)

Handel videre

Gå til kassen
VISA/DK VISA/DK VISA/DK VISA/DK VISA/DK
Find forhandler

,

Tlf.

Se alle
Error executing template "Designs/Mobler2018/eCom/Product/Product.cshtml"
System.InvalidOperationException: Sequence contains no elements
   at System.Linq.Enumerable.Last[TSource](IEnumerable`1 source)
   at CompiledRazorTemplates.Dynamic.RazorEngine_36ef731205104aca8422d1e5ed6524be.Execute() in D:\dynamicweb.net\Solutions\mobler.LIVE\Files\Templates\Designs\Mobler2018\eCom\Product\Product.cshtml:line 136
   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.b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @using System.Web 2 @using Mobler.Website.CustomModules.MoblerHelpers 3 @using System.Text.RegularExpressions 4 @using CampaignModule.Models 5 @using Group = Dynamicweb.Ecommerce.Products.Group 6 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 7 8 9 @{ 10 string shopname = MoblerHelpers.GetShopName(); 11 string SelectPlaceholder = Translate("ShopSelectPlaceholder", "Indtast by, postnummer eller adresse"); 12 var shopInfo = MoblerHelpers.ShopInfo(); 13 int ShopPageId = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetInt("ShopPageId"); 14 var AllShops = Firstweb.Custom.CustomCode.Frontend.Helpers.Shops.GetAllShops(ShopPageId); 15 int AjaxCartPageId = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetInt("AjaxCartPageId"); 16 int CustomersAlsoSawPageId = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetInt("CustomersAlsoSawPageId"); 17 string CartPage = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("CartPage"); 18 string VariantsEndpoint = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("VariantsUrl"); 19 string VariantDetailsEndpoint = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("VariantDetailsUrl"); 20 string BlackFridayTheme = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("BlackFridayTheme"); 21 string ProductID = GetString("Ecom:Product.ID"); 22 string GroupID = Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.GetProductDefaultShopGroupID(ProductID); //GetString("Ecom:Product.PrimaryOrFirstGroupID"); 23 string DefaultVariantID = GetString("Ecom:Product.DefaultVariantComboID"); 24 string ProductImage = MoblerHelpers.GetProductListImage(ProductID, DefaultVariantID); 25 string ProductName = GetString("Ecom:Product.Name"); 26 string ProductNumber = GetString("Ecom:Product.Number"); 27 string ProductCatalogLink = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.ProductCatelog.Value.Clean")) ? GetString("Ecom:Product:Field.ProductCatelog.Value.Clean") : ""; 28 string VariantId = GetString("Ecom:Product.VariantID"); 29 string ShortDescription = GetString("Ecom:Product.ShortDescription"); 30 string LongDescription = GetString("Ecom:Product.LongDescription").Replace("||", "<br/>"); 31 string CurrentVariantName = GetString("Ecom:Product.SelectedVariantComboName"); 32 var FaqQuestions = MoblerHelpers.GetProductFAQs(ProductID, GroupID); 33 34 35 Mobler.Website.CustomCode.Frontend.PayeverHelper payeverHelper = new Mobler.Website.CustomCode.Frontend.PayeverHelper(); 36 Mobler.Website.CustomCode.Models.PayeverWidget PayeverWidget = payeverHelper.GetPayeverWidgetInformation(); 37 38 string MetaDescription = GetString("Ecom:Product.MetaDescription"); 39 40 if (string.IsNullOrEmpty(MetaDescription)) 41 { 42 MetaDescription = Mobler.Website.CustomCode.Frontend.Helpers.Text.GetFirstLine(LongDescription.Replace("<br/>", " ")); 43 } 44 else 45 { 46 MetaDescription = ""; //Meta data description bliver sat af DW, hvis dette felt er udfyldt, så vi skal ikke opsætte noget. 47 } 48 49 50 var RelatedBlogs = Firstweb.Custom.CustomCode.Frontend.Helpers.Blogs.GetBlogsRelatedToProduct(ProductID); 51 bool NewItem = GetBoolean("Ecom:Product:Field.NewItem"); 52 DateTime NewItemExpiryDate = GetDate( "Ecom:Product:Field.NewItemExpiryDate" ); 53 bool LowPrice = GetBoolean("Ecom:Product:Field.Splash3"); 54 55 56 Mobler.Website.CustomCode.Frontend.ProductsDisplayVariant productsDisplayVariant = Mobler.Website.CustomCode.Frontend.ProductsDisplayVariant.Instance(); 57 58 bool ForSale = !GetBoolean("Ecom:Product:Field.NotForSaleOnline"); 59 60 var MainProdNr = string.Empty; 61 var VariantNr = string.Empty; 62 string FirstImage = ""; 63 if (!string.IsNullOrWhiteSpace(ProductNumber)) 64 { 65 string[] MainProdSplit = ProductNumber.Split('_'); 66 67 68 69 if (MainProdSplit.Length > 1) 70 { 71 MainProdNr = MainProdSplit[0]; 72 VariantNr = MainProdSplit[1]; 73 } 74 else 75 { 76 MainProdNr = ProductNumber; 77 } 78 } 79 var Images = MoblerHelpers.GetProductImages(GetString("Ecom:Product.ID"), VariantId); 80 bool First = true; 81 bool FirstIndicator = true; 82 int IndicatorIncrementer = 0; 83 string ProductLink = GetString("Ecom:Product.Link.Clean"); 84 85 double ActualPrice = GetDouble("Ecom:Product.Price.Price"); 86 double spar = 0; 87 double price = 0; 88 double normalPrice = 0; 89 90 string priceFormatted = ""; 91 string sparFormatted = ""; 92 string normalPriceFormatted = ""; 93 94 string campaignColor = ""; 95 string campaignText = ""; 96 string campaignDate = ""; 97 98 99 string campaignDateStart = ""; 100 string campaignDateEnd = ""; 101 102 103 bool CampaignActiveOnProduct = GetBoolean("CampaignModule:Product.CampaignActiveOnProduct"); 104 if (!CampaignActiveOnProduct) 105 { 106 price = ActualPrice; 107 priceFormatted = MoblerHelpers.formatPrice(price); 108 } 109 else 110 { 111 normalPrice = GetDouble("CampaignModule:Product.CampaignProduct.NormalPrice"); 112 normalPriceFormatted = GetString("CampaignModule:Product.CampaignProduct.NormalPrice.FormattedRetail"); 113 114 price = GetDouble("CampaignModule:Product.CampaignProduct.CampaignPrice"); 115 priceFormatted = GetString("CampaignModule:Product.CampaignProduct.CampaignPrice.FormattedRetail"); 116 117 spar = GetDouble("CampaignModule:Product.CampaignProduct.DiscountAmount"); 118 sparFormatted = GetString("CampaignModule:Product.CampaignProduct.DiscountAmount.FormattedRetail"); 119 120 campaignColor = GetString("CampaignModule:Product.Campaign.Color"); 121 campaignText = GetString("CampaignModule:Product.Campaign.Text"); 122 123 campaignDateStart = GetString("CampaignModule:Product.CampaignProduct.Campaign.Start"); 124 campaignDateEnd = GetString("CampaignModule:Product.CampaignProduct.Campaign.End"); 125 } 126 127 128 string DataLayerPrice = ActualPrice.ToString().Replace(".", "").Replace(",", "."); 129 System.Web.HttpContext.Current.Items["OverrideOgTags"] = true; 130 string OgImage = "https://mobler.dk" + Images.FirstOrDefault(); 131 132 string TrimmedTeaser = Firstweb.Custom.CustomCode.Frontend.Helpers.JSFormatting.TrimLinebreaks(ShortDescription); 133 string TrimmedName = Firstweb.Custom.CustomCode.Frontend.Helpers.JSFormatting.TrimLinebreaks(ProductName); 134 135 var ParentGroups = Firstweb.Custom.CustomCode.Frontend.Helpers.EcomGroups.getBreadCrumbGroupList(GroupID, true); 136 var DataLayerParentGroup = ParentGroups.Last().Name; 137 List<string> DataLayerParentGroupStrings = ParentGroups.Select(group => group.Name).ToList(); 138 string DataLayerParentGroups = string.Join(" > ", DataLayerParentGroupStrings); 139 140 string ShowOnPageUrl = ""; 141 string GetCartEndpoint = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("GetCartJson"); 142 143 string QuickDeliveryColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("QuickDeliveryColor"); 144 string QuickDeliveryDescription = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("QuickDeliveryDescription"); 145 string NormalDeliveryDescription = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("NormalDeliveryDescription"); 146 string BrandName = GetString("Ecom:Product:Field.Maerkevarer.Value.Clean"); 147 string DeliveryTime = Translate("DeliveryTime." + BrandName, "Gns. leveringstid 3-12 dage"); 148 bool HideDelivery = DeliveryTime == "Skjul"; 149 string DeliveryColor = "#00AB5D"; 150 bool QuickDelivery = GetBoolean("Ecom:Product:Field.QuickDelivery.Value.Clean"); 151 string CustomDelivery = GetString("Ecom:Product:Field.CustomDeliveryTime.Value.Clean"); 152 if (QuickDelivery) 153 { 154 DeliveryColor = QuickDeliveryColor; 155 DeliveryTime = Translate("DeliveryTime.QuickDelivery", "Ekstra hurtig levering"); 156 } 157 else if (!String.IsNullOrEmpty(CustomDelivery)) 158 { 159 DeliveryTime = CustomDelivery; 160 } 161 string DeliveryFontWeightModifier = QuickDelivery ? "font-weight-bold" : ""; 162 bool DisplayAverageDeliveryTime = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetBoolean("DisplayAverageDeliveryTime"); 163 164 double CostPrice = GetDouble("Ecom:Product:Field.FirstwebCostPrice.Value.Raw"); 165 string DailyPriceBackgroundColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("AktuelDagsprisBackgroundColor"); 166 string DailyPriceTextColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("AktuelDagsprisTextColor"); 167 string EAN = GetString("Ecom:Product:Field.FirstEan.Value"); 168 169 string productionDescription = GetString("Ecom:Product:Field.FirstwebProductionDescription"); 170 171 172 Mobler.Website.CustomCode.RelewiseCustom.RelewiseCaller relewiseCaller = new Mobler.Website.CustomCode.RelewiseCustom.RelewiseCaller(); 173 relewiseCaller.TrackProductView(ProductID, VariantId); 174 175 } 176 177 178 @SnippetStart("ProductDetailsMeta") 179 @if (!string.IsNullOrEmpty(MetaDescription)) 180 { 181 <meta name="description" content="@MetaDescription" /> 182 } 183 @SnippetEnd("ProductDetailsMeta") 184 185 @SnippetStart("OgTags") 186 <meta property="og:type" content="product" /> 187 <meta property="og:description" content="@Regex.Replace(ShortDescription, "<.*?>", String.Empty)" /> 188 <meta property="og:image" content="@OgImage" /> 189 @SnippetEnd("OgTags") 190 191 @using System.Collections 192 @using Dynamicweb.Ecommerce 193 @using Mobler.Website.CustomModules.MoblerHelpers 194 @using Dynamicweb.Ecommerce.Products 195 @using Dynamicweb.Ecommerce.Variants 196 @using Humanizer 197 @using Mobler.Website.CustomCode 198 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 199 200 @using Mobler.Website.CustomModules.MoblerHelpers 201 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 202 203 @helper RenderPricing(LoopItem product, bool hasVariants) 204 { 205 // Theming 206 string blackFridayTheme = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("BlackFridayTheme"); 207 208 // Pricing 209 DateTime newItemExpiryDate = product.GetDate( "Ecom:Product:Field.NewItemExpiryDate" ); 210 bool hasNewItemExpiryDate = newItemExpiryDate.Date > DateTime.Now.Date; 211 bool newItem = product.GetBoolean("Ecom:Product:Field.NewItem") && hasNewItemExpiryDate; 212 bool LowPrice = product.GetBoolean("Ecom:Product:Field.Splash3"); 213 double CostPrice = product.GetDouble("Ecom:Product:Field.FirstwebCostPrice.Value.Raw"); 214 string PriceSaving = product.GetString("Ecom:Product:Field.Spar.Value"); 215 double ActualPrice = product.GetDouble("Ecom:Product.Price.Price"); 216 217 // Initialize variables 218 double spar = 0; 219 double price = 0; 220 double normalPrice = 0; 221 222 string priceFormatted = ""; 223 string sparFormatted = ""; 224 string normalPriceFormatted = ""; 225 226 string campaignColor = ""; 227 string campaignText = ""; 228 string campaignDate = ""; 229 230 bool CampaignActiveOnProduct = product.GetBoolean("CampaignModule:Product.CampaignActiveOnProduct"); 231 if (!CampaignActiveOnProduct) 232 { 233 price = ActualPrice; 234 priceFormatted = MoblerHelpers.formatPrice(price); 235 } 236 else 237 { 238 normalPrice = product.GetDouble("CampaignModule:Product.CampaignProduct.NormalPrice"); 239 normalPriceFormatted = product.GetString("CampaignModule:Product.CampaignProduct.NormalPrice.FormattedRetail"); 240 241 price = product.GetDouble("CampaignModule:Product.CampaignProduct.CampaignPrice"); 242 priceFormatted = product.GetString("CampaignModule:Product.CampaignProduct.CampaignPrice.FormattedRetail"); 243 244 spar = product.GetDouble("CampaignModule:Product.CampaignProduct.DiscountAmount"); 245 sparFormatted = product.GetString("CampaignModule:Product.CampaignProduct.DiscountAmount.FormattedRetail"); 246 247 campaignColor = product.GetString("CampaignModule:Product.Campaign.Color"); 248 campaignText = product.GetString("CampaignModule:Product.Campaign.Text"); 249 } 250 251 // Set Splash Types 252 string splashType = ""; 253 if (campaignText == "KOMBI") 254 { 255 splashType = "combo"; 256 } 257 else if (CostPrice > 0) 258 { 259 splashType = "priceshape"; 260 } 261 else if (spar > 0) 262 { 263 splashType = "offer"; 264 } 265 else if (newItem) 266 { 267 splashType = "new"; 268 } 269 else if (LowPrice) 270 { 271 splashType = "low"; 272 } 273 274 <div> 275 <p class="product-item__price fs3 font-weight-bold"> 276 @if (hasVariants) 277 { 278 <span class="font-weight-semibold fs0 mr-2">@Translate("ProductPrice.From", "Fra")</span> 279 } 280 @priceFormatted 281 </p> 282 @if (splashType == "combo") 283 { 284 <div class="splash splash--on-top"> 285 <p class="m-0">@Translate("ProductCombinationOffer", "Sætpris")</p> 286 </div> 287 <div class="d-flex justify-content-between mb-2"> 288 <p class="color-subtle fs0 m-0 text-uppercase">@Translate("PriceBefore", "Før") @normalPriceFormatted</p> 289 <p class="splash fs0 text-uppercase m-0 px-2">@Translate("PriceSaving", "Spar") @sparFormatted</p> 290 </div> 291 } 292 else if (splashType == "priceshape") 293 { 294 string DailyPriceBackgroundColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("AktuelDagsprisBackgroundColor"); 295 string DailyPriceTextColor = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("AktuelDagsprisTextColor"); 296 297 <div class="splash splash--on-top price-shape" style="background-color: @DailyPriceBackgroundColor"> 298 <p class="m-0" style="color: @DailyPriceTextColor;">@Translate("ProductDailyPriceSplash", "Dagspris")</p> 299 </div> 300 } 301 else if (splashType == "offer") 302 { 303 if (blackFridayTheme == "True") 304 { 305 <div class="splash splash--on-top bf-bg-black bf-color-white"> 306 <p class="m-0">@Translate("ProductOffer", "Tilbud")</p> 307 </div> 308 } 309 else 310 { 311 <div class="splash splash--on-top p-1"> 312 <p class="m-0">@Translate("ProductOffer", "Tilbud")</p> 313 </div> 314 } 315 <div class="d-flex justify-content-between mb-2"> 316 <p class="color-subtle fs0 m-0 text-uppercase">@Translate("PriceBefore", "Før") @normalPriceFormatted</p> 317 <p class="splash fs0 m-0 text-uppercase px-2">@Translate("PriceSaving", "Spar") @sparFormatted</p> 318 </div> 319 } 320 else if (splashType == "new") 321 { 322 <div class="splash splash--on-top new-item"> 323 <p class="m-0">@Translate("ProductNew", "Nyhed")</p> 324 </div> 325 } 326 else if (splashType == "low") 327 { 328 <div class="splash splash--on-top low-price"> 329 <p class="m-0">@Translate("ProductLowPrice", "Fast lavpris")</p> 330 </div> 331 } 332 </div> 333 } 334 335 336 @helper RenderProduct(LoopItem product) 337 { 338 // Group Specific - Exclude Bed Accessories 339 bool excludeBedAccessories = product.GetBoolean("Ecom:Product.CategoryField.Senge.ExcludeBedAccessories.Value"); 340 341 // Product General Info 342 string productId = product.GetString("Ecom:Product.ID"); 343 string productName = product.GetString("Ecom:Product.Name"); 344 string productLink = product.GetString("Ecom:Product.Link.Clean"); 345 string shortDescription = product.GetString("Ecom:Product.ShortDescription"); 346 string languageId = product.GetString("Ecom:Product.LanguageID"); 347 348 // Variants 349 string defaultVariantId = product.GetString("Ecom:Product.DefaultVariantComboID"); 350 string variantId = product.GetString("Ecom:Product.VariantID"); 351 if (String.IsNullOrEmpty(variantId)) { 352 variantId = defaultVariantId; 353 } 354 if (!String.IsNullOrEmpty(variantId)) { 355 productLink = productLink + "&variantid=" + variantId; 356 } 357 358 359 // Check if product has variants 360 bool hasVariants = false; 361 362 // Product Images 363 List<string> images = MoblerHelpers.GetProductImages(productId, variantId); 364 string productImage = string.Format("/Admin/Public/GetImage.ashx?Image={0}&Width=280&height=220&Format=png&Crop=5&resolution=50", images.FirstOrDefault()); //MoblerHelpers.GetProductListImageWithMainImage(ProductID, ProductNumber); 365 366 // Product Dimensions 367 string productDepth = product.GetString("Ecom:Product:Field.dybdeint.Value.Clean"); 368 string productHeight = product.GetString("Ecom:Product:Field.hoejdeint.Value.Clean"); 369 string productWidth = product.GetString("Ecom:Product:Field.breddeint.Value.Clean"); 370 bool hasProductDepth = !string.IsNullOrWhiteSpace(productDepth) && productDepth != "0"; 371 bool hasProductHeight = !string.IsNullOrWhiteSpace(productHeight) && productHeight != "0"; 372 bool hasProductWidth = !string.IsNullOrWhiteSpace(productWidth) && productWidth != "0"; 373 374 // Campaign 375 string campaignDateStart = ""; 376 string campaignDateEnd = ""; 377 378 bool campaignActiveOnProduct = product.GetBoolean("CampaignModule:Product.CampaignActiveOnProduct"); 379 if (campaignActiveOnProduct) 380 { 381 campaignDateStart = product.GetString("CampaignModule:Product.CampaignProduct.Campaign.Start"); 382 campaignDateEnd = product.GetString("CampaignModule:Product.CampaignProduct.Campaign.End"); 383 } 384 385 bool hasCampaignDateStart = !string.IsNullOrWhiteSpace(campaignDateStart); 386 387 bool hasCampaignDateEnd = !string.IsNullOrWhiteSpace(campaignDateEnd); 388 string campaignText = ""; 389 if (hasCampaignDateStart && hasCampaignDateStart) 390 { 391 campaignText = $"{Translate("Campaign.BeforeDate.Text", "Gældende fra:")} {campaignDateStart} {Translate("Campaign.BeforeDate.Text2", "t.o.m.")} {campaignDateEnd}"; 392 } 393 394 <div class="col-12 col-sm-6 col-lg-3 product-item js-product-list-item"> 395 <div class="product-item__header"> 396 <a href="@productLink" class="product-item__image"> 397 <img class="js-product-image-@productId" src="@productImage" alt="@productName" loading="lazy"/> 398 </a> 399 400 401 </div> 402 403 <div class="product-item__body"> 404 <a href="@productLink" class="product-item__title"> 405 <h3 class="fs0">@productName</h3> 406 </a> 407 <div class="product-item__description fs0 color-subtle">@shortDescription</div> 408 @if (hasProductDepth || hasProductHeight || hasProductWidth) 409 { 410 <p class="product-item__dimensions fs0 color-subtle"> 411 @if (hasProductDepth) 412 { 413 <span>D/L: @productDepth</span> 414 } 415 @if (hasProductHeight) 416 { 417 <span>H: @productHeight</span> 418 } 419 @if (hasProductWidth) 420 { 421 <span>B: @productWidth</span> 422 } 423 </p> 424 } 425 </div> 426 427 <div class="product-item__footer"> 428 @RenderPricing(product, hasVariants) 429 430 @if (excludeBedAccessories) 431 { 432 <p class="color-subtle fs-s m-0">@Translate("Ecom:Product.Pricing.Excludes.Beds", "Prisen er ekskl. ben og gavl.")</p> 433 } 434 @if (hasVariants) 435 { 436 <div class="variant-price-disclaimer color-subtle fs-s">@Translate("VariantPriceDisclaimer", "Prisen kan variere efter materialevalg")</div> 437 } 438 @if (hasCampaignDateStart && hasCampaignDateEnd) 439 { 440 <div class="product-item__campaign"> 441 <p class="color-subtle fs-s">@campaignText</p> 442 </div> 443 } 444 </div> 445 </div> 446 } 447 448 @using Mobler.Website.CustomModules.MoblerHelpers 449 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 450 451 @helper RenderBlogTeaser(Firstweb.Custom.CustomCode.Frontend.Helpers.Blog Blog) 452 { 453 string PageId = GetGlobalValue( "Global:Page.ID" ); 454 string CleanLink = Blog.Link.Replace("default.aspx?id", "Default.aspx?Id"); 455 <div class="col-12 col-md-4 px-0 px-md-3 mb-4"> 456 <a href="@CleanLink" class="blog d-block"> 457 <div class="image" style="background-image:url('@Blog.Image')"> 458 <img class="d-none" src="@Blog.Image" alt="Alternate Text" /> 459 </div> 460 <div class="text"> 461 <div class="positioning"> 462 <h4 class="col-10 col-md-9 px-2 pt-3 bg-white font-weight-bold text-center mx-auto">@Blog.Header</h4> 463 @if ( PageId != "7613" ) 464 { 465 <p class="text-center color-subtle">@Blog.Date</p> 466 } 467 <p class="text-center font-weight-bold m-0 color-primary">@Translate("BlogReadMore", "L&aelig;s mere her")</p> 468 </div> 469 </div> 470 </a> 471 </div> 472 } 473 474 @helper RenderLargeBlogTeaser(Firstweb.Custom.CustomCode.Frontend.Helpers.Blog Blog, string ImagePosition) 475 { 476 string ImageClass = ImagePosition == "Left" ? "" : "offset-md-4"; 477 string TextClass = ImagePosition == "Left" ? "" : "left"; 478 string Image = "/Admin/Public/GetImage.ashx?Image=" + Blog.Image + "&Height=400&Crop=0"; 479 string CleanLink = Blog.Link.Replace("default.aspx?id", "Default.aspx?Id"); 480 <div class="col-12 blog"> 481 <div class="row"> 482 <div class="col-12 col-md-8 px-0 px-md-3 @ImageClass"> 483 <div class="image-container" style="background-image:url('@Image')"> 484 <img class="img-fluid" src="@Image" alt="@Blog.Header" /> 485 </div> 486 </div> 487 <div class="col-12 col-md-6 text-container mb-5 mb-md-0 @TextClass"> 488 <div class="text bg-white p-3"> 489 <div> 490 <h4>@Blog.Header</h4> 491 @Blog.Teaser 492 </div> 493 <a class="font-weight-bold" href="@CleanLink">@Translate("BlogReadMore", "L&aelig;s mere her")</a> 494 </div> 495 </div> 496 </div> 497 </div> 498 } 499 500 @helper RenderLatestBlogsTeasers() 501 { 502 var LatestBlogs = Firstweb.Custom.CustomCode.Frontend.Helpers.Blogs.GetLatestBlogs(); 503 foreach (var Blog in LatestBlogs) 504 { 505 @RenderBlogTeaser(Blog) 506 } 507 } 508 509 510 <div class="container pt-3 d-none d-md-block"> 511 512 <div class="bread"> 513 <p class="color-subtle">@Translate("Breadcrumb.CurrentPage", "Her er du:")</p> 514 <p class="bread-item color-subtle"> 515 <a href="/"> 516 @Translate("Breadcrumb.Frontpage", "Forside") 517 </a> 518 </p> 519 @foreach (var Group in ParentGroups) 520 { 521 <p class="bread-item color-subtle"> 522 @if (Group == ParentGroups.First()) 523 { 524 @Group.Name 525 ShowOnPageUrl = Group.ProductGroupFieldValues.GetProductGroupFieldValue("FirstwebGroupPrimaryPage").Value.ToString(); 526 } 527 else 528 { 529 <a href="/@ShowOnPageUrl&GroupId=@Group.Id"> 530 @Group.Name 531 </a> 532 } 533 </p> 534 } 535 536 <p class="active color-subtle">@ProductName</p> 537 </div> 538 539 </div> 540 541 <div class="container mt-3 mb-5 product-details position-relative" data-bind="viewModel: 'ProductViewModel'"> 542 543 <div class="d-none" data-bind="setInitValue: { observable: CartPageId, value: '@AjaxCartPageId' }"></div> 544 <div class="d-none" data-bind="setInitValue: { observable: MiniCart, value: '.js-mini-cart-lines' }"></div> 545 <div class="d-none" data-bind="setInitValue: { observable: CartCount, value: '.js-cart-count' }"></div> 546 <div class="d-none" data-bind="setInitValue: { observable: CustomersAlsoSawLines, value: '.js-customers-also-saw-lines' }"></div> 547 <div class="d-none" data-bind="setInitValue: { observable: CustomersAlsoSawPage, value: '@CustomersAlsoSawPageId' }"></div> 548 <div class="d-none" data-bind="setInitValue: { observable: MainProductId, value: '@ProductID' }"></div> 549 <div class="d-none" data-bind="setInitValue: { observable: VariantsEndpoint, value: '@VariantsEndpoint' }"></div> 550 <div class="d-none" data-bind="setInitValue: { observable: VariantDetailsEndpoint, value: '@VariantDetailsEndpoint' }"></div> 551 <div class="d-none" data-bind="setInitValue: { observable: TeaserText, value: '@TrimmedTeaser' }"></div> 552 <div class="d-none" data-bind="setInitValue: { observable: ProductName, value: '@TrimmedName' }"></div> 553 <div class="d-none" data-bind="setInitValue: { observable: ProductNumber, value: '@ProductNumber' }"></div> 554 <div class="d-none" data-bind="setInitValue: { observable: VariantId, value: '@VariantId' }"></div> 555 <div class="d-none" data-bind="setInitValue: { observable: Price, value: '@priceFormatted' }"></div> 556 <div class="d-none js-update-cart" data-bind="setInitValue: { observable: CartEndpoint, value: '@GetCartEndpoint' }, click: GetCart"></div> 557 558 <div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls"> 559 <div class="slides"></div> 560 <h3 class="title"></h3> 561 <a class="prev">&#8249;</a> 562 <a class="next">&#8250;</a> 563 <a class="close">x</a> 564 <a class="play-pause"></a> 565 <ol class="indicator"></ol> 566 </div> 567 568 <div class="modal fade video-modal" id="videoModal" tabindex="-1" role="dialog" aria-labelledby="video-modal" aria-hidden="true"> 569 <div class="modal-dialog modal-dialog-centered" role="document"> 570 <div class="modal-content"> 571 <div class="modal-body"> 572 <div id="player"></div> 573 </div> 574 </div> 575 </div> 576 </div> 577 578 <div class="add-to-cart-overlay" data-bind="css: { 'd-block': ProcessingAjax }"> 579 <p class="fs4 m-0 color-white">@Translate("ProductAjaxAddingToCart", "Tilf&oslash;jer til kurv") <i class="fa fa-spinner fa-spin ml-3 fs5"></i></p> 580 </div> 581 582 <div class="add-to-cart-overlay" data-bind="css: { 'd-block': ProcessingVariantDetailsAjax }"> 583 <p class="fs4 m-0 color-white">@Translate("ProductAjaxGettingVariant", "Henter variant") <i class="fa fa-spinner fa-spin ml-3 fs5"></i></p> 584 </div> 585 586 <div class="delivery-information-popup" data-bind="css: { 'd-flex': DeliveryInfoOpen }, click: ToggleDeliveryInfo"> 587 <div class="description-content bg-white px-3 py-4 px-lg-4 position-relative" data-bind="click: OpenDeliveryInfo, clickBubble: false"> 588 <div class="modal-closer-custom" data-bind="click: ToggleDeliveryInfo, clickBubble: false"> 589 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/close.svg" /> 590 </div> 591 @if (QuickDelivery) 592 { 593 <div> 594 @QuickDeliveryDescription 595 </div> 596 } 597 else if (DisplayAverageDeliveryTime) 598 { 599 <div> 600 @NormalDeliveryDescription 601 </div> 602 } 603 </div> 604 </div> 605 606 @if (CostPrice > 0) 607 { 608 string PriceDescription = Firstweb.Custom.CustomCode.Frontend.Helpers.AreaItems.GetString("DagsprisDescription"); 609 <div class="delivery-information-popup" data-bind="css: { 'd-flex': PriceInfoOpen }, click: TogglePriceInfo"> 610 <div class="description-content bg-white px-3 py-4 px-lg-4 position-relative" data-bind="click: OpenPriceInfo, clickBubble: false"> 611 <div class="modal-closer-custom" data-bind="click: TogglePriceInfo, clickBubble: false"> 612 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/close.svg" /> 613 </div> 614 <div> 615 @PriceDescription 616 </div> 617 </div> 618 </div> 619 } 620 621 <h1 class="header mb-4" data-bind="text: ProductName">@ProductName</h1> 622 623 <div class="d-flex flex-wrap"> 624 625 <div class="image-container position-relative overflow-hidden"> 626 627 <div class="splash splash--on-top unimportant-hidden" data-bind="css: { 'd-flex': SplashType() == 1 }"><p class="m-0">@Translate("ProductOffer", "Tilbud")</p></div> 628 <div class="splash splash--on-top unimportant-hidden new-item" data-bind="css: { 'd-flex': SplashType() == 2 }"><p class="m-0">@Translate("ProductNew", "Nyhed")</p></div> 629 <div class="splash splash--on-top unimportant-hidden low-price" data-bind="css: { 'd-flex': SplashType() == 3 }"><p class="m-0">@Translate("ProductLowPrice", "Fast lavpris")</p></div> 630 <div class="splash splash--on-top unimportant-hidden price-shape" data-bind="css: { 'd-flex': SplashType() == 4 }" style="background-color: @DailyPriceBackgroundColor;"><p class="m-0" style="color: @DailyPriceTextColor;">@Translate("ProductDailyPriceSplash", "Dagspris")</p></div> 631 <div class="splash splash--on-top unimportant-hidden splash--small" data-bind="css: { 'd-flex': SplashType() == 5}"><p class="m-0">@Translate("ProductCombinationOffer", "Sætpris")</p></div> 632 633 <div id="imageSlider" class="carousel slide" data-ride="carousel" data-interval="5000"> 634 <div class="carousel-inner align-items-center" data-bind="if: Images().length == 0"> 635 636 @foreach (var Image in Images) 637 { 638 if (First) 639 { 640 <a href="/Admin/Public/GetImage.ashx?Image=@Image&width=2000" class="mb-3 mb-lg-0 carousel-item active" data-gallery> 641 <img class="product-image main-image" src="/Admin/Public/GetImage.ashx?Image=@Image&width=950&height=500&crop=5" alt="@ProductName" /> 642 </a> 643 First = false; 644 FirstImage = "/Admin/Public/GetImage.ashx?Image=" + Image + "&width=950&height=500&crop=5"; 645 } 646 else 647 { 648 <a href="/Admin/Public/GetImage.ashx?Image=@Image&width=2000" class="mb-3 mb-lg-0 carousel-item" data-gallery> 649 <img class="product-image main-image" src="/Admin/Public/GetImage.ashx?Image=@Image&width=950&height=500&crop=5" alt="@ProductName" /> 650 </a> 651 } 652 653 } 654 655 </div> 656 <div class="carousel-inner align-items-center d-flex js-ko-carousel" data-bind="foreach: Images()"> 657 658 <a data-bind="attr: { href: '/Admin/Public/GetImage.ashx?Image=' + $data + '&width=2000' }" class="mb-3 mb-lg-0 carousel-item active" data-gallery> 659 <img class="product-image main-image" data-bind="attr: { src: '/Admin/Public/GetImage.ashx?Image=' + $data + '&width=950&height=500&crop=5' }" /> 660 </a> 661 662 </div> 663 </div> 664 665 @if (Images.Count > 0) 666 { 667 <div class="row small-gutter carousel-row" data-bind="css: { 'd-none': Images().length > 0 }"> 668 @if (Images.Count > 1) 669 { 670 foreach (var Image in Images) 671 { 672 if (FirstIndicator) 673 { 674 <div data-target="#imageSlider" data-slide-to="@IndicatorIncrementer" class="col-4 mt-lg-3 cursor-pointer active"> 675 <div class="secondary-image"> 676 <img class="product-image" src="/Admin/Public/GetImage.ashx?Image=@Image&width=400&height=230&crop=5" alt="@ProductName" /> 677 </div> 678 </div> 679 FirstIndicator = false; 680 } 681 else 682 { 683 <div data-target="#imageSlider" data-slide-to="@IndicatorIncrementer" class="col-4 mt-lg-3 cursor-pointer"> 684 <div class="secondary-image"> 685 <img class="product-image" src="/Admin/Public/GetImage.ashx?Image=@Image&width=400&height=230&crop=5" alt="@ProductName" /> 686 </div> 687 </div> 688 } 689 IndicatorIncrementer++; 690 } 691 } 692 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoKlip.Value"))) 693 { 694 string BackgroundSize = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoBillede.Value.Clean")) ? "cover" : "contain"; 695 string OverlayImage = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoBillede.Value.Clean")) ? GetString("Ecom:Product:Field.VideoBillede.Value.Clean") : FirstImage; 696 <div class="youtube-video-container mt-lg-3" style="min-height:120px;" data-bind="youtubeVideo: { videoId: '@GetString("Ecom:Product:Field.VideoKlip.Value")', overlayId: 'js-video-overlay', playerId: 'player' }"> 697 <div id="js-video-overlay" class="video-overlay pointer" style="background-image:url('@OverlayImage');background-size: @BackgroundSize;"> 698 <div class="visual-overlay d-flex flex-column justify-content-center align-items-center h-100 w-100"> 699 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/Play.svg" /> 700 <p class="mt-3 mb-0 color-white">@Translate("Product.WatchVideo", "Se video")</p> 701 </div> 702 </div> 703 </div> 704 } 705 706 </div> 707 708 <div class="row small-gutter carousel-row unimportant-hidden" data-bind="css: { 'd-flex': Images().length > 0 }"> 709 <span class="images" style="display:contents;" data-bind="foreach: Images()"> 710 <!-- ko if: $index() == 0 --> 711 <div data-target="#imageSlider" class="col-4 mt-lg-3 cursor-pointer active" data-bind="click: $parent.ChangeSlide.bind($data, $index())"> 712 <div class="secondary-image"> 713 <img class="product-image" data-bind="attr: { src: '/Admin/Public/GetImage.ashx?Image=' + $data + '&width=400&height=230&crop=5' }" alt="@ProductName" /> 714 </div> 715 </div> 716 <!-- /ko --> 717 <!-- ko if: $index() != 0 --> 718 <div data-target="#imageSlider" class="col-4 mt-lg-3 cursor-pointer" data-bind="click: $parent.ChangeSlide.bind($data, $index())"> 719 <div class="secondary-image"> 720 <img class="product-image" data-bind="attr: { src: '/Admin/Public/GetImage.ashx?Image=' + $data + '&width=400&height=230&crop=5' }" alt="@ProductName" /> 721 </div> 722 </div> 723 <!-- /ko --> 724 </span> 725 726 @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoKlip.Value"))) 727 { 728 string BackgroundSize = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoBillede.Value.Clean")) ? "cover" : "contain"; 729 string OverlayImage = !String.IsNullOrEmpty(GetString("Ecom:Product:Field.VideoBillede.Value.Clean")) ? GetString("Ecom:Product:Field.VideoBillede.Value.Clean") : FirstImage; 730 <div class="youtube-video-container mt-lg-3" data-bind="youtubeVideo: { videoId: '@GetString("Ecom:Product:Field.VideoKlip.Value")', overlayId: 'js-videovariant-overlay', playerId: 'player' }"> 731 <div id="js-videovariant-overlay" class="video-overlay pointer" style="background-image:url('@OverlayImage');background-size: @BackgroundSize;"> 732 <div class="visual-overlay d-flex flex-column justify-content-center align-items-center h-100 w-100"> 733 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/Play.svg" /> 734 <p class="mt-3 mb-0 color-white">@Translate("Product.WatchVideo", "Se video")</p> 735 </div> 736 </div> 737 </div> 738 } 739 </div> 740 } 741 742 </div> 743 744 <div class="pl-lg-4 description-container d-flex flex-wrap flex-column mt-3 mt-lg-0 position-relative"> 745 746 <div class="mb-2">@ShortDescription</div> 747 748 <div class="w-100"><p class="color-primary pointer mb-2" data-bind="scrollToElement: { target: '#js-full-description' }">@Translate("ProductReadFullDescription", "L&aelig;s hele beskrivelsen")</p></div> 749 750 <div class="w-100"> 751 <p class="color-subtle m-0">@Translate("ProductProductNumber", "Produktnummer:") <span data-bind="text: ProductNumber">@ProductNumber</span></p> 752 <p class="color-subtle m-0"> 753 @if (!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.dybdeint.Value.Clean"))) 754 { 755 if (GetString("Ecom:Product:Field.dybdeint.Value.Clean") != "0") 756 { 757 <span>D/L: @GetValue("Ecom:Product:Field.dybdeint.Value.Clean")</span> 758 } 759 } 760 @if (!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.hoejdeint.Value.Clean"))) 761 { 762 if (GetString("Ecom:Product:Field.hoejdeint.Value.Clean") != "0") 763 { 764 <span>H: @GetValue("Ecom:Product:Field.hoejdeint.Value.Clean")</span> 765 } 766 } 767 @if (!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.breddeint.Value.Clean"))) 768 { 769 if (GetString("Ecom:Product:Field.breddeint.Value.Clean") != "0") 770 { 771 <span>B: @GetValue("Ecom:Product:Field.breddeint.Value.Clean")</span> 772 } 773 } 774 </p> 775 </div> 776 777 @if ((QuickDelivery || DisplayAverageDeliveryTime) && !HideDelivery) 778 { 779 <div class="w-100 mt-3"> 780 781 <div class="delivery-information"> 782 <svg class="delivery-icon mr-2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" fill="@DeliveryColor" x="0px" y="0px" width="30px" height="30px" viewBox="0 0 612 612" style="enable-background:new 0 0 612 612;" xml:space="preserve"> 783 <g> 784 <g> 785 <path d="M226.764,375.35c-28.249,0-51.078,22.91-51.078,51.16c0,28.166,22.829,51.078,51.078,51.078s51.078-22.912,51.078-51.078 C277.841,398.26,255.013,375.35,226.764,375.35z M226.764,452.049c-14.125,0-25.54-11.498-25.54-25.541 c0-14.123,11.415-25.539,25.54-25.539c14.124,0,25.539,11.416,25.539,25.539C252.302,440.551,240.888,452.049,226.764,452.049z M612,337.561v54.541c0,13.605-11.029,24.635-24.636,24.635h-26.36c-4.763-32.684-32.929-57.812-66.927-57.812 c-33.914,0-62.082,25.129-66.845,57.812H293.625c-4.763-32.684-32.93-57.812-66.845-57.812c-33.915,0-62.082,25.129-66.844,57.812 h-33.012c-13.606,0-24.635-11.029-24.635-24.635v-54.541H612L612,337.561z M494.143,375.35c-28.249,0-51.16,22.91-51.16,51.16 c0,28.166,22.912,51.078,51.16,51.078c28.166,0,51.077-22.912,51.077-51.078C545.22,398.26,522.309,375.35,494.143,375.35z M494.143,452.049c-14.125,0-25.539-11.498-25.539-25.541c0-14.123,11.414-25.539,25.539-25.539 c14.042,0,25.539,11.416,25.539,25.539C519.682,440.551,508.185,452.049,494.143,452.049z M602.293,282.637l-96.817-95.751 c-6.159-6.077-14.453-9.526-23.076-9.526h-48.86v-18.313c0-13.631-11.004-24.635-24.635-24.635H126.907 c-13.55,0-24.635,11.005-24.635,24.635v3.86L2.3,174.429l177.146,23.068L0,215.323l178.814,25.423L0,256.25l102.278,19.29 l-0.007,48.403h509.712v-17.985C611.983,297.171,608.452,288.796,602.293,282.637z M560.084,285.839h-93.697 c-2.135,0-3.86-1.724-3.86-3.859v-72.347c0-2.135,1.725-3.86,3.86-3.86h17.82c0.985,0,1.971,0.411,2.71,1.068l75.796,72.347 C565.257,281.569,563.532,285.839,560.084,285.839z" /> 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 </g> 802 </g> 803 </svg> 804 <p class="delivery-text @DeliveryFontWeightModifier">@DeliveryTime - <a href="#" class="text-underline" data-bind="click: ToggleDeliveryInfo" style="color: @DeliveryColor">@Translate("Product.DeliveryInfo.ReadmoreText", "L&aelig;s mere")</a></p> 805 </div> 806 807 </div> 808 } 809 810 @if (CostPrice > 0) 811 { 812 <div class="w-100 mt-3"> 813 814 <div class="delivery-information"> 815 <div class="live-price-animation"></div> 816 <p class="delivery-text">@Translate("Product.PriceInfo.RecommendedPriceInfo", "Aktuel dagspris - ")<a href="#" class="text-underline" data-bind="click: TogglePriceInfo">@Translate("Product.PriceInfo.RecommendedPriceLink", "L&aelig;s mere")</a></p> 817 </div> 818 819 </div> 820 } 821 822 823 <div class="w-100"> 824 @if (GetBoolean("Ecom:Product:Field.Farvevarianter1.Value")) 825 { 826 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver1.png" /> 827 <p class="mb-0">@Translate("ProductColor1Text", "F&aring;s i flere forskellige varianter og moduler, bes&oslash;g dit lokale M&oslash;blér bolighus og f&aring; vejledning til design af din sofa.")</p> 828 } 829 else if (GetBoolean("Ecom:Product:Field.Farvevarianter2.Value")) 830 { 831 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver2.png" /> 832 <p class="mb-0">@Translate("ProductColor2Text", "Farve 2 hj&aelig;lpetekst")</p> 833 } 834 else if (GetBoolean("Ecom:Product:Field.Farvevarianter3.Value")) 835 { 836 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver3.png" /> 837 <p class="mb-0">@Translate("ProductColor3Text", "Farve 3 hj&aelig;lpetekst")</p> 838 } 839 else if (GetBoolean("Ecom:Product:Field.Farvevarianter4.Value")) 840 { 841 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver4.png" /> 842 <p class="mb-0">@Translate("ProductColor4Text", "Farve 4 hj&aelig;lpetekst")</p> 843 } 844 else if (GetBoolean("Ecom:Product:Field.Farvevarianter5.Value")) 845 { 846 <img class="img-fluid mb-3 mt-5" src="/Files/Images/Farver/farver5.png" /> 847 <p class="mb-0">@Translate("ProductColor5Text", "Farve 5 hj&aelig;lpetekst")</p> 848 } 849 </div> 850 @if (GetLoop("VariantCombinations").Count > 0) 851 { 852 var VariantGroupsWithMultipleOptions = GetLoop("VariantGroups").Where(x => x.GetLoop("VariantAvailableOptions").Count > 1); 853 int VariantGroupCount = VariantGroupsWithMultipleOptions.Count(); 854 int VariantCombinationsCount = GetLoop("VariantCombinations").Count; 855 int PossibleVariantCombinations = 1; 856 foreach (var VG in GetLoop("VariantGroups")) 857 { 858 PossibleVariantCombinations *= VG.GetLoop("VariantAvailableOptions").Count; 859 } 860 if (VariantGroupCount == 1) 861 { 862 var RelevantVariantGroup = VariantGroupsWithMultipleOptions.FirstOrDefault(); 863 var SelectedVariant = RelevantVariantGroup.GetLoop("VariantAvailableOptions").Where(x => x.GetBoolean("Ecom:VariantOption.Selected")).FirstOrDefault(); 864 <div class="position-relative"> 865 <div class="variant-dropdown p-2 box-shadow mt-3 d-flex justify-content-between align-items-center pointer js-variant-dropdown"> 866 <p class="m-0"><span class="font-weight-bold">@RelevantVariantGroup.GetString("Ecom:VariantGroup.Label")</span> - <span data-bind="text: SelectedVariantOption0">@SelectedVariant.GetString("Ecom:VariantOption.Name")</span></p> 867 <i class="fas fa-chevron-down"></i> 868 </div> 869 <div class="variant-options bg-white"> 870 @foreach (var Variant in RelevantVariantGroup.GetLoop("VariantAvailableOptions")) 871 { 872 var VariantCombination = GetLoop("VariantCombinations").Where(x => x.GetString("Ecom:VariantCombination.VariantID").ToString().Contains(Variant.GetString("Ecom:VariantOption.ID"))).FirstOrDefault(); 873 string VariantName = Variant.GetString("Ecom:VariantOption.Name"); 874 string VariantIdentifier = Variant.GetString("Ecom:VariantOption.ID"); 875 string VariantLink = VariantCombination.GetString("Ecom:VariantCombination.Link.Clean"); 876 string VariantPreview = String.Empty; 877 var ObservableToSet = "SelectedVariantOption0"; 878 var ObservableToSetId = "SelectedVariantOptionId0"; 879 bool ShowPreview = RelevantVariantGroup.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("farve") || RelevantVariantGroup.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("materiale") ? true : false; 880 if (!String.IsNullOrEmpty(Variant.GetString("Ecom:VariantOption.ImgSmall.Clean")) && ShowPreview) 881 { 882 if (Variant.GetString("Ecom:VariantOption.ImgSmall.Clean").StartsWith("#")) 883 { 884 VariantPreview = "style= \"background-color: " + Variant.GetString("Ecom:VariantOption.ImgSmall.Clean") + ";\""; 885 } 886 else 887 { 888 VariantPreview = "style=\"background-image: url('" + Variant.GetString("Ecom:VariantOption.ImgSmall.Clean") + "');\""; 889 } 890 } 891 <div class="option pointer color-primary d-flex w-100 p-2 bg-grey" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VariantIdentifier', @ObservableToSet, '@VariantName', @ObservableToSetId)"> 892 @if (!String.IsNullOrEmpty(VariantPreview)) 893 { 894 <span class="option-preview mr-2" @VariantPreview></span> 895 } 896 <span>@VariantName</span> 897 </div> 898 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSet, value: '@SelectedVariant.GetString("Ecom:VariantOption.Name")' }"></div> 899 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSetId, value: '@SelectedVariant.GetString("Ecom:VariantOption.ID")' }"></div> 900 901 } 902 </div> 903 </div> 904 } 905 else if (PossibleVariantCombinations == VariantCombinationsCount) 906 { 907 Dictionary<string, string> CurrentlySelectedVariantOptions = new Dictionary<string, string>(); 908 foreach (var VG in GetLoop("VariantGroups")) 909 { 910 foreach (var VO in VG.GetLoop("VariantAvailableOptions").Where(x => x.GetBoolean("Ecom:VariantOption.Selected"))) 911 { 912 CurrentlySelectedVariantOptions.Add(VG.GetString("Ecom:VariantGroup.Name"), VO.GetString("Ecom:VariantOption.ID")); 913 } 914 } 915 int VGLoopCounter = 0; 916 foreach (var VG in GetLoop("VariantGroups")) 917 { 918 List<LoopItem> RelevantVariantCombinations = new List<LoopItem>(); 919 var VariantCombinationLink = GetLoop("VariantCombinations"); 920 var SelectedVariant = VG.GetLoop("VariantAvailableOptions").Where(x => x.GetBoolean("Ecom:VariantOption.Selected")).FirstOrDefault(); 921 var ObservableToSet = "SelectedVariantOption" + VGLoopCounter.ToString(); 922 var ObservableToSetId = "SelectedVariantOptionId" + VGLoopCounter.ToString(); 923 VGLoopCounter++; 924 foreach (var VC in VariantCombinationLink) 925 { 926 var Add = true; 927 foreach (var KVP in CurrentlySelectedVariantOptions.Where(s => s.Key != VG.GetString("Ecom:VariantGroup.Name"))) 928 { 929 if (!VC.GetString("Ecom:VariantCombination.VariantID").ToString().Contains(KVP.Value)) 930 { 931 Add = false; 932 } 933 } 934 if (Add) 935 { 936 RelevantVariantCombinations.Add(VC); 937 } 938 } 939 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSet, value: '@SelectedVariant.GetString("Ecom:VariantOption.Name")' }"></div> 940 <div class="d-none" data-bind="setInitValue: { observable: @ObservableToSetId, value: '@SelectedVariant.GetString("Ecom:VariantOption.ID")' }"></div> 941 942 943 <div class="position-relative"> 944 <div class="variant-dropdown p-2 box-shadow mt-3 d-flex justify-content-between align-items-center pointer js-variant-dropdown"> 945 <p class="m-0"><span class="font-weight-bold">@VG.GetString("Ecom:VariantGroup.Label")</span> - <span data-bind="text: @ObservableToSet">@SelectedVariant.GetString("Ecom:VariantOption.Name")</span></p> 946 <i class="fas fa-chevron-down"></i> 947 </div> 948 <div class="variant-options bg-white"> 949 @foreach (var VO in VG.GetLoop("VariantAvailableOptions")) 950 { 951 var VariantCombination = RelevantVariantCombinations.Where(vc => vc.GetString("Ecom:VariantCombination.VariantID").ToString().Contains(VO.GetString("Ecom:VariantOption.ID"))).FirstOrDefault(); 952 string VariantLink = VariantCombination.GetString("Ecom:VariantCombination.Link.Clean"); 953 string VariandOptionId = VariantCombination.GetString("Ecom:VariantCombination.VariantID"); 954 string VariantPreview = String.Empty; 955 string VOName = VO.GetString("Ecom:VariantOption.Name"); 956 string VOId = VO.GetString("Ecom:VariantOption.ID"); 957 bool ShowPreview = VG.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("farve") || VG.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("materiale") ? true : false; 958 if (!String.IsNullOrEmpty(VO.GetString("Ecom:VariantOption.ImgSmall.Clean")) && ShowPreview) 959 { 960 if (VO.GetString("Ecom:VariantOption.ImgSmall.Clean").StartsWith("#")) 961 { 962 VariantPreview = "style= \"background-color: " + VO.GetString("Ecom:VariantOption.ImgSmall.Clean") + ";\""; 963 } 964 else 965 { 966 VariantPreview = "style=\"background-image: url('" + VO.GetString("Ecom:VariantOption.ImgSmall.Clean") + "');\""; 967 } 968 } 969 <div class="option d-flex w-100 p-2 bg-grey color-primary pointer" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VOId', @ObservableToSet, '@VOName', @ObservableToSetId)"> 970 @if (!String.IsNullOrEmpty(VariantPreview)) 971 { 972 <span class="option-preview mr-2" @VariantPreview></span> 973 } 974 @VOName 975 </div> 976 } 977 </div> 978 </div> 979 } 980 } 981 else if (GetLoop("VariantGroups").Where(x => x.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("farve")).Count() > 0 && GetLoop("VariantGroups").Where(x => x.GetString("Ecom:VariantGroup.Name").ToString().ToLower().Contains("materiale")).Count() > 0) 982 { 983 <div class="mt-3"> 984 <p class="mb-1">@Translate("CurrentDesignName", "Valgte design: ")</p> 985 <p class="font-weight-bold">@CurrentVariantName</p> 986 </div> 987 <div class="d-flex"> 988 <div class="btn btn-primary" data-bind="click: ToggleVariantPicker">@Translate("ChooseNewDesign", "V&aelig;lg design")</div> 989 </div> 990 } 991 else 992 { 993 var SelectedVariant = GetLoop("VariantCombinations").Where(x => x.GetBoolean("Ecom:VariantCombination.Selected")).FirstOrDefault(); 994 var SelectedVariantName = SelectedVariant.GetString("Ecom:VariantCombination.VariantText"); 995 var SelectedVariantId = SelectedVariant.GetString("Ecom:VariantOption.ID"); 996 <div class="d-none" data-bind="setInitValue: { observable: SelectedVariantOption0, value: '@SelectedVariantName' }"></div> 997 <div class="d-none" data-bind="setInitValue: { observable: SelectedVariantOptionId0, value: '@SelectedVariantId' }"></div> 998 <div class="position-relative"> 999 <div class="variant-dropdown p-2 box-shadow mt-3 d-flex justify-content-between align-items-center pointer js-variant-dropdown"> 1000 <p class="m-0"><span class="font-weight-bold">@Translate("FallbackVariantsText", "VARIANTER")</span> - <span data-bind="text: SelectedVariantOption0">@SelectedVariantName</span></p> 1001 <i class="fas fa-chevron-down"></i> 1002 </div> 1003 <div class="variant-options bg-white"> 1004 @foreach (var Variant in GetLoop("VariantCombinations")) 1005 { 1006 string VariantName = Variant.GetString("Ecom:VariantCombination.VariantText"); 1007 string VariantLink = Variant.GetString("Ecom:VariantCombination.Link.Clean"); 1008 string VCId = Variant.GetString("Ecom:Product.VariantID"); 1009 <div class="option color-primary pointer d-block p-2 bg-grey" data-bind="click: UpdateVariantAndSetObservable.bind($data, '@VCId', SelectedVariantOption0, '@VariantName', SelectedVariantOptionId0)">@VariantName</div> 1010 } 1011 </div> 1012 </div> 1013 } 1014 1015 } 1016 1017 <div class="row align-items-end f-grow-1"> 1018 <div class="col-10 offset-1 col-sm-12 offset-sm-0 d-flex justify-content-center justify-content-lg-start"> 1019 1020 <div class="mt-5 d-flex flex-wrap flex-column justify-content-end"> 1021 @if (campaignText == "KOMBI") 1022 { 1023 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 5 }"></div> 1024 <div class="d-none" data-bind="setInitValue: { observable: BeforePrice, value: '@normalPriceFormatted' }"></div> 1025 <div class="d-none" data-bind="setInitValue: { observable: Saving, value: '@sparFormatted' }"></div> 1026 } 1027 else if (spar > 0) 1028 { 1029 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 1 }"></div> 1030 <div class="d-none" data-bind="setInitValue: { observable: BeforePrice, value: '@normalPriceFormatted' }"></div> 1031 <div class="d-none" data-bind="setInitValue: { observable: Saving, value: '@sparFormatted' }"></div> 1032 } 1033 else if (NewItem) 1034 { 1035 if ( NewItemExpiryDate > DateTime.Now ) 1036 { 1037 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 2 }"></div> 1038 } 1039 } 1040 else if (LowPrice) 1041 { 1042 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 3 }"></div> 1043 } 1044 else if (CostPrice > 0) 1045 { 1046 <div class="d-none" data-bind="setInitValue: { observable: SplashType, value: 4 }"></div> 1047 } 1048 1049 <div class="w-100 unimportant-hidden" data-bind="css: { 'd-flex': SplashType() == 1 || SplashType() == 5}"> 1050 <p class="color-subtle fs0 m-0 text-uppercase mr-3">@Translate("PriceBefore", "Før") <span data-bind="text: BeforePrice"></span></p> 1051 <p class="splash fs0 text-uppercase m-0 px-2">@Translate("PriceSaving", "Spar") <span data-bind="text: Saving"></span></p> 1052 </div> 1053 <p class="price font-weight-bold m-0"> 1054 <span class="unimportant-hidden" data-bind="css: { 'd-inline': SplashType() == 1 }">@Translate("ProductNow", "NU") </span> 1055 <span data-bind="text: Price"></span> 1056 </p> 1057 1058 1059 @if (!string.IsNullOrEmpty(campaignDateStart) && !string.IsNullOrEmpty(campaignDateEnd)) 1060 { 1061 string CampaignText = $"{Translate("Campaign.BeforeDate.Text", "Gældende fra:")} {campaignDateStart} {Translate("Campaign.BeforeDate.Text2", "t.o.m.")} {campaignDateEnd}"; 1062 <div class="d-none" data-bind="setInitValue: { observable: CampaignText, value: '@CampaignText' }"></div> 1063 } 1064 else 1065 { 1066 <div class="d-none" data-bind="setInitValue: { observable: CampaignText, value: '' }"></div> 1067 } 1068 1069 <p data-bind="text: CampaignText"></p> 1070 1071 @if (!string.IsNullOrEmpty(PayeverWidget.WidgetId) && !string.IsNullOrEmpty(PayeverWidget.BusinessId) && !string.IsNullOrEmpty(PayeverWidget.CheckoutId)) 1072 { 1073 <div> 1074 <div class="payever-widget-finexp" 1075 data-widgetid="@PayeverWidget.WidgetId" 1076 data-checkoutid="@PayeverWidget.CheckoutId" 1077 data-business="@PayeverWidget.BusinessId" 1078 data-type="text" 1079 data-reference="order-id" 1080 data-amount="@GetString("Ecom:Product.Price.Price").Replace(".", string.Empty).Replace(",", ".")"></div> 1081 <script> 1082 var script = document.createElement('script'); 1083 script.src = 'https://widgets.payever.org/finance-express/widget.min.js'; 1084 script.onload = function() { 1085 PayeverPaymentWidgetLoader.init( 1086 '.payever-widget-finexp' 1087 ); 1088 }; 1089 document.head.appendChild(script); 1090 </script> 1091 </div> 1092 } 1093 1094 @if (ForSale) 1095 { 1096 <div class="d-flex align-items-center mt-3"> 1097 <p class="m-0 font-weight-bold fs1 mr-2">@Translate("Product.Quantity", "Antal")</p> 1098 <div class="d-flex"> 1099 <div class="quantity-controls d-flex align-items-center mr-3"> 1100 <div class="control minus" data-bind="click: DecreaseQuantity"> 1101 - 1102 </div> 1103 <input type="text" name="Quantity" value="1" data-bind="value: Quantity" /> 1104 <div class="control plus" data-bind="click: IncrementQuantity"> 1105 + 1106 </div> 1107 </div> 1108 @{ 1109 string addToCartButtonClass = BlackFridayTheme == "True" ? "btn-black-friday bf-bg-black" : "btn-primary"; 1110 } 1111 <p class="btn @addToCartButtonClass add-to-cart m-0 d-flex align-items-center px-4" data-bind="click: AddToCart.bind($data, '@DataLayerPrice')"> 1112 @Translate("ProductAddToCart", "L&aelig;g i kurv") 1113 </p> 1114 1115 </div> 1116 </div> 1117 } 1118 else 1119 { 1120 <p>@Translate("Ecom:Product.NotForSaleMessage", "Produktet kan ikke købes.")</p> 1121 } 1122 </div> 1123 </div> 1124 </div> 1125 1126 </div> 1127 1128 </div> 1129 1130 <div class="d-flex flex-wrap justify-content-center external-ctas"> 1131 1132 @if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ProviderLink.Value.Clean"))) 1133 { 1134 <a href="@GetString("Ecom:Product:Field.ProviderLink.Value.Clean")" target="_blank" class="bg-brand font-weight-bold d-flex align-items-center justify-content-center no-underline p-3 color-white"> 1135 <span>@Translate("Product.DesignSelf", "Design selv")</span> 1136 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/Pencil1.svg" /> 1137 </a> 1138 } 1139 1140 @if (!String.IsNullOrEmpty(ProductCatalogLink)) 1141 { 1142 <a class="btn btn-secondary rounded-0 d-flex justify-content-center align-items-center p-3 color-white font-weight-bold" href="@ProductCatalogLink" target="_blank"> 1143 <span>@Translate("ProductProductCatalogLink", "Se inspirationsbrochure")</span> 1144 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/Brochure.svg" /> 1145 </a> 1146 } 1147 1148 </div> 1149 1150 <div class="d-flex flex-wrap mt-5"> 1151 1152 <div id="js-full-description"> 1153 <p class="fs3 mb-2 font-weight-bold">@Translate("ProductDescriptionHeader", "Beskrivelse")</p> 1154 <div class="unimportant-hidden" data-bind="html: FullDescription, css: { 'd-block': FullDescription().length > 0 }"> 1155 </div> 1156 <div data-bind="css: { 'd-none': FullDescription().length > 0 }"> 1157 @LongDescription 1158 1159 @if (!string.IsNullOrEmpty(productionDescription)) 1160 { 1161 <br /><br /> 1162 <h4>@Translate("Product.ProductionDescription.Headline", "Produktionsbeskrivelse")</h4> 1163 @:@productionDescription 1164 } 1165 </div> 1166 </div> 1167 1168 </div> 1169 1170 <div class="d-flex flex-wrap my-5"> 1171 1172 <div class="description-container mt-5 mt-lg-0"> 1173 <div class="bg-brand color-white box-shadow p-3 pb-5 questions"> 1174 <img class="staff-img" src="/Files/Templates/Designs/Mobler2018/assets/img/sovnmand.png" /> 1175 1176 @if (!String.IsNullOrWhiteSpace(shopInfo.ShopName) && shopInfo.ShopName != "Møblér") 1177 { 1178 <div class="shop-info"> 1179 <h4 class="fs45">@Translate("ProductQuestionsHeader", "Har du sp&oslash;rsm&aring;l?")</h4> 1180 <p class="mb-1">@shopInfo.Address, @shopInfo.PostalAndCity</p> 1181 <p class="mb-1">@shopInfo.Phone</p> 1182 @if (!String.IsNullOrEmpty(shopInfo.Email)) 1183 { 1184 <p class="mb-1"><a class="color-white" href="mailto:@shopInfo.Email">@shopInfo.Email</a></p> 1185 } 1186 @if (!String.IsNullOrEmpty(shopInfo.ShopName1)) 1187 { 1188 <p class="mb-1 mt-2">@shopInfo.Address1, @shopInfo.PostalAndCity1</p> 1189 <p class="mb-2">@shopInfo.Phone1</p> 1190 } 1191 @if (!String.IsNullOrEmpty(shopInfo.ShopName2)) 1192 { 1193 <p class="mb-1 mt-2">@shopInfo.Address2, @shopInfo.PostalAndCity2</p> 1194 <p class="mb-2">@shopInfo.Phone2</p> 1195 } 1196 @shopInfo.OpeningHours 1197 </div> 1198 } 1199 else 1200 { 1201 <h4 class="fs45">@Translate("ProductQuestionsHeader", "Har du sp&oslash;rsm&aring;l?")</h4> 1202 <p class="fs2 text">@Translate("ProductSelectNearestShop", "V&aelig;lg n&aelig;rmeste M&oslash;bler bolighus")</p> 1203 <select style="width: 280px;" data-bind="select2SelectShop: { overlay: 'find-dealer-overlay', placeholder: '@SelectPlaceholder' }"> 1204 @if (shopname == "Møblér") 1205 { 1206 <option selected disabled>@Translate("HeaderFindShop", "Find forhandler")</option> 1207 } 1208 else 1209 { 1210 foreach (var Shop in AllShops.Where(x => x.MenuText == shopname)) 1211 { 1212 <option selected disabled value="@HttpUtility.UrlEncode(Shop.MenuText)">@Shop.ShopName</option> 1213 } 1214 } 1215 @foreach (var Shop in AllShops) 1216 { 1217 if (Shop.MenuText != "Møblér" && Shop.MenuText != shopname) 1218 { 1219 var Address = "<div>" + Shop.Address + "</div><div>" + Shop.PostalAndCity + "</div>"; 1220 <option title="@Address" value="@HttpUtility.UrlEncode(Shop.MenuText)">@Shop.ShopName {{@Shop.PostalAndCity @Shop.SearchKeyWords}}</option> 1221 } 1222 } 1223 </select> 1224 } 1225 </div> 1226 </div> 1227 1228 </div> 1229 1230 @if (GetInteger("Ecom:Product.RelatedCount") > 0) 1231 { 1232 foreach (var Group in GetLoop("ProductRelatedGroups").Where(g => g.GetLoop("Products").Count > 0)) 1233 { 1234 <div class="py-3 mt-5" data-bind="viewModel: 'ProductListViewModel'"> 1235 1236 <div class="delivery-information-popup" data-bind="css: { 'd-flex': QuickDeliveryInfoOpen }, click: ToggleQuickDeliveryInfo"> 1237 <div class="description-content bg-white px-3 py-4 px-lg-4 position-relative" data-bind="click: OpenQuickDeliveryInfo, clickBubble: false"> 1238 <div class="modal-closer-custom" data-bind="click: ToggleQuickDeliveryInfo, clickBubble: false"> 1239 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/close.svg" /> 1240 </div> 1241 <div> 1242 @QuickDeliveryDescription 1243 </div> 1244 </div> 1245 </div> 1246 <div class="delivery-information-popup" data-bind="css: { 'd-flex': NormalDeliveryInfoOpen }, click: ToggleNormalDeliveryInfo"> 1247 <div class="description-content bg-white px-3 py-4 px-lg-4 position-relative" data-bind="click: OpenNormalDeliveryInfo, clickBubble: false"> 1248 <div class="modal-closer-custom" data-bind="click: ToggleNormalDeliveryInfo, clickBubble: false"> 1249 <img src="/Files/Templates/Designs/Mobler2018/assets/img/icons/close.svg" /> 1250 </div> 1251 <div> 1252 @NormalDeliveryDescription 1253 </div> 1254 </div> 1255 </div> 1256 1257 <div class="line-through-header mb-3"> 1258 <h4>@Group.GetString("Ecom:Product:RelatedGroup.Name")</h4> 1259 </div> 1260 1261 <div class="row"> 1262 1263 @foreach (var Product in Group.GetLoop("Products")) 1264 { 1265 var productToRender = Product; 1266 string productId = Product.GetString("Ecom:Product.ID"); 1267 string variantIdLoop = productsDisplayVariant.GetDisplayVariantId(productId); 1268 1269 if (Product.GetLoop("VariantCombinations").Count > 0 && Product.GetLoop("VariantCombinations").Any(x => x.GetString("Ecom:Product.VariantID").Equals(variantIdLoop))) 1270 { 1271 productToRender = Product.GetLoop("VariantCombinations").FirstOrDefault(x => x.GetString("Ecom:Product.VariantID").Equals(variantIdLoop)); 1272 } 1273 @RenderProduct(productToRender) 1274 } 1275 </div> 1276 </div> 1277 } 1278 } 1279 1280 1281 @if(Mobler.Website.CustomCode.RelewiseCustom.RelewiseConnectorSetting.ShowRecommendations) 1282 { 1283 if (GetLoop("RelewiseRecommendationProducts").Count > 0) 1284 { 1285 <div class="py-3 mt-5" data-bind="viewModel: 'ProductListViewModel'"> 1286 1287 1288 <div class="line-through-header mb-3"> 1289 <h4>@Translate("Product:RelewiseRecommendationProducts.Headline", "Vi anbefaler du også tjekker disse produkter ud...")</h4> 1290 </div> 1291 1292 <div class="row"> 1293 1294 @foreach (var Product in GetLoop("RelewiseRecommendationProducts")) 1295 { 1296 var productToRender = Product; 1297 string productId = Product.GetString("Ecom:Product.ID"); 1298 string variantIdLoop = productsDisplayVariant.GetDisplayVariantId(productId); 1299 1300 if (Product.GetLoop("VariantCombinations").Count > 0 && Product.GetLoop("VariantCombinations").Any(x => x.GetString("Ecom:Product.VariantID").Equals(variantIdLoop))) 1301 { 1302 productToRender = Product.GetLoop("VariantCombinations").FirstOrDefault(x => x.GetString("Ecom:Product.VariantID").Equals(variantIdLoop)); 1303 } 1304 1305 @RenderProduct(productToRender) 1306 } 1307 </div> 1308 </div> 1309 } 1310 } 1311 1312 1313 @if (RelatedBlogs.Count > 0) 1314 { 1315 string ImagePosition = "Left"; 1316 <div class="feature-blogs my-5"> 1317 1318 <div class="row"> 1319 1320 @foreach (var Blog in RelatedBlogs) 1321 { 1322 @RenderLargeBlogTeaser(Blog, ImagePosition) 1323 if (ImagePosition == "Left") 1324 { 1325 ImagePosition = "Right"; 1326 } 1327 else 1328 { 1329 ImagePosition = "Left"; 1330 } 1331 } 1332 1333 </div> 1334 1335 </div> 1336 } 1337 1338 1339 <div class="after-add-to-cart bg-white box-shadow" data-bind="css: { 'd-block': ProductAddedToCart }"> 1340 <div class="closer fs3 pointer" data-bind="click: ProductAddedToCart(false)"> 1341 <i class="fas fa-times-circle color-primary"></i> 1342 </div> 1343 <div class="p-3"> 1344 <p class="font-weight-bold fs4 text-uppercase m-0"> 1345 <i class="fas fa-check-circle color-primary"></i> 1346 @Translate("ProductProductAddedToCart", "Varen er lagt i indk&oslash;bskurven") 1347 </p> 1348 </div> 1349 <div class="mini-cart large-cart power-step"> 1350 1351 <div class="position-relative"> 1352 <div class="cart-command-loader unimportant-hidden justify-content-center align-items-center" data-bind="css: { 'd-flex': Loading }"> 1353 <div class="d-flex align-items-center"> 1354 <p class="m-0 mr-2">@Translate("Cart.UpdatingCart", "Opdaterer kurv")</p> 1355 <i class="fas fa-spinner fa-spin"></i> 1356 </div> 1357 </div> 1358 1359 <div class="lines" data-bind="foreach: Orderlines"> 1360 <div class="cartline d-flex justify-content-between align-items-center px-3 py-2 position-relative bg-grey"> 1361 <span class="delete-orderline color-subtle cursor-pointer mr-2" data-bind="click: $parent.DeleteOrderline.bind($data, OrderlineId)"> 1362 <i class="fas fa-times"></i> 1363 </span> 1364 <div class="product-image w-10"> 1365 <img class="img-fluid" data-bind="attr: { src: ImagePath }" /> 1366 </div> 1367 <div class="flex-fill px-3 w-75"> 1368 <p class="font-weight-bold m-0" data-bind="text: ProductName"></p> 1369 <p class="m-0 color-subtle small-quantity-indicator"><span data-bind="text: Quantity"></span> stk. a <span data-bind="text: QuantityPrice"></span></p> 1370 <div class="variant-dimensions" data-bind="foreach: VariantDimensions"> 1371 <p class="m-0 color-subtle color-dark-grey font-weight-bold"> 1372 <span data-bind="text: Label"></span> 1373 <span class="font-weight-normal" data-bind="text: Value"></span> 1374 </p> 1375 </div> 1376 </div> 1377 <div class="qty-counter w-10"> 1378 <div class="d-flex"> 1379 <div class="quantity-controls d-flex align-items-center mr-3"> 1380 <div class="control minus" data-bind="click: $parent.QuantityControl.bind($data, -1, OrderlineId)"> 1381 - 1382 </div> 1383 <input disabled type="text" name="Quantity" value="1" data-bind="value: Quantity, attr: { 'data-id': 'js-input-' + OrderlineId }" /> 1384 <div class="control plus" data-bind="click: $parent.QuantityControl.bind($data, 1, OrderlineId)"> 1385 + 1386 </div> 1387 </div> 1388 </div> 1389 </div> 1390 1391 <p class="fs0 m-0 orderline-price" data-bind="text: OrderlinePrice"></p> 1392 </div> 1393 </div> 1394 @if (BlackFridayTheme == "True") 1395 { 1396 <div class="bf-bg-black p-3 d-flex justify-content-between align-items-center price-summary"> 1397 <p class="m-0 color-white fs-12px font-weight-semibold">@Translate("MiniCartTotal", "Din kurv i alt (ex. fragt)")</p> 1398 <p class="m-0 color-white fs1 font-weight-bold" data-bind="text: CartTotalNoFees"></p> 1399 </div> 1400 } 1401 else 1402 { 1403 <div class="bg-brand p-3 d-flex justify-content-between align-items-center price-summary"> 1404 <p class="m-0 color-white fs-12px font-weight-semibold">@Translate("MiniCartTotal", "Din kurv i alt (ex. fragt)")</p> 1405 <p class="m-0 color-white fs1 font-extra-bold" data-bind="text: CartTotalNoFees"></p> 1406 </div> 1407 } 1408 </div> 1409 1410 </div> 1411 <div class="p-3 d-flex justify-content-between"> 1412 <p class="pointer py-2 px-3 bg-dark-grey color-white rounded m-0" data-bind="click: ProductAddedToCart(false)">@Translate("MiniCartContinueShopping", "Handel videre")</p> 1413 1414 @if (BlackFridayTheme == "True") 1415 { 1416 <a href="@CartPage" class="pointer py-2 px-3 bf-bg-black color-white rounded d-block no-underline">@Translate("MiniCartGoToCheckout", "G&aring; til kassen")</a> 1417 } 1418 else 1419 { 1420 <a href="@CartPage" class="pointer py-2 px-3 bg-brand color-white rounded d-block no-underline">@Translate("MiniCartGoToCheckout", "G&aring; til kassen")</a> 1421 } 1422 1423 </div> 1424 <div class="js-customers-also-saw-lines"></div> 1425 1426 </div> 1427 <div class="variant-picker" data-bind="css: { 'open': VariantPickerOpen }"> 1428 <div class="closer color-primary fs5 pointer" data-bind="click: ToggleVariantPicker"> 1429 <i class="fas fa-times-circle"></i> 1430 </div> 1431 <div class="container py-5 position-relative"> 1432 <h3 class="fs4 text-center">Design din @ProductName</h3> 1433 @{ 1434 var ColorDimensions = GetLoop("VariantGroups").Where(g => g.GetString("Ecom:VariantGroup.Name").ToLower().Contains("farve")); 1435 var NonColorDimensions = GetLoop("VariantGroups").Where(g => !g.GetString("Ecom:VariantGroup.Name").ToLower().Contains("farve")); 1436 int FilterCounter = 0; 1437 string RowClass = NonColorDimensions.Any() && ColorDimensions.Any() ? "flex-row-reverse" : ""; 1438 } 1439 <div class="row mt-5 @RowClass"> 1440 @if (ColorDimensions.Any()) 1441 { 1442 <div class="col-12 col-md-8"> 1443 @foreach (var VariantDimension in ColorDimensions) 1444 { 1445 string DimensionName = VariantDimension.GetString("Ecom:VariantGroup.Name"); 1446 string FilterName = "filter-" + FilterCounter; 1447 FilterCounter++; 1448 <div class="mb-5 mb-md-0"> 1449 <p class="font-weight-bold fs2 mb-2">@DimensionName</p> 1450 <div class="row custom-row"> 1451 @foreach (var VariantOption in VariantDimension.GetLoop("VariantAvailableOptions").OrderBy(v => v.GetString("Ecom:VariantOption.Name"))) 1452 { 1453 string VariantOptionName = VariantOption.GetString("Ecom:VariantOption.Name"); 1454 string VariantOptionId = VariantOption.GetString("Ecom:VariantOption.ID"); 1455 string Preview = VariantOption.GetString("Ecom:VariantOption.ImgSmall.Clean"); 1456 string PreviewCss = ""; 1457 if (!String.IsNullOrEmpty(Preview)) 1458 { 1459 if (Preview.StartsWith("#")) 1460 { 1461 PreviewCss = "style= \"background-color: " + Preview + ";\""; 1462 } 1463 else 1464 { 1465 PreviewCss = "style=\"background-image: url('" + Preview + "');\""; 1466 } 1467 } 1468 <div class="col-2 col-sm-3 col-md-2 mb-3 d-flex flex-column justify-content-end pointer color-variant" data-bind="click: AddToFilter.bind($data, $element, '@FilterName', '@VariantOptionId')"> 1469 <p class="mb-0 color-variant-name d-none d-sm-block">@VariantOptionName</p> 1470 <div class="variant-preview position-relative d-flex" @PreviewCss></div> 1471 </div> 1472 } 1473 </div> 1474 </div> 1475 } 1476 </div> 1477 } 1478 @if (NonColorDimensions.Any()) 1479 { 1480 <div class="col-12 col-sm-6 col-md-4"> 1481 @foreach (var VariantDimension in NonColorDimensions) 1482 { 1483 string DimensionName = VariantDimension.GetString("Ecom:VariantGroup.Name"); 1484 string FilterName = "filter-" + FilterCounter; 1485 FilterCounter++; 1486 <div class="mb-5"> 1487 <p class="font-weight-bold fs2 mb-2">@DimensionName</p> 1488 <div class="row custom-row"> 1489 @foreach (var VariantOption in VariantDimension.GetLoop("VariantAvailableOptions").OrderBy(v => v.GetString("Ecom:VariantOption.Name"))) 1490 { 1491 string VariantOptionName = VariantOption.GetString("Ecom:VariantOption.Name"); 1492 string VariantOptionId = VariantOption.GetString("Ecom:VariantOption.ID"); 1493 string Preview = VariantOption.GetString("Ecom:VariantOption.ImgSmall.Clean"); 1494 string PreviewCss = ""; 1495 if (!String.IsNullOrEmpty(Preview)) 1496 { 1497 if (Preview.StartsWith("#")) 1498 { 1499 PreviewCss = "style= \"background-color: " + Preview + ";\""; 1500 } 1501 else 1502 { 1503 PreviewCss = "style=\"background-image: url('/Files" + Preview + "');\""; 1504 } 1505 } 1506 if (DimensionName == "STØRRELSE") 1507 { 1508 <div class="col-6 col-sm-4 mb-3 d-flex flex-column justify-content-end pointer size-variant" data-bind="click: AddToFilter.bind($data, $element, '@FilterName', '@VariantOptionId')"> 1509 <div class="variant-preview position-relative d-flex justify-content-center align-items-center" @PreviewCss> 1510 <p class="mb-0 color-variant-name font-weight-bold">@VariantOptionName</p> 1511 </div> 1512 </div> 1513 } 1514 else 1515 { 1516 <div class="col-6 col-sm-4 mb-3 d-flex flex-column justify-content-end pointer" data-bind="click: AddToFilter.bind($data, $element, '@FilterName', '@VariantOptionId')"> 1517 <p class="mb-0 color-variant-name">@VariantOptionName</p> 1518 <div class="variant-preview position-relative d-flex" @PreviewCss></div> 1519 </div> 1520 } 1521 } 1522 </div> 1523 </div> 1524 } 1525 </div> 1526 } 1527 1528 <div class="col-12 d-flex justify-content-end"> 1529 <p class="color-primary pointer my-3" data-bind="click: ResetFilters">Nulstil</p> 1530 </div> 1531 </div> 1532 <p class="font-weight-bold fs2 mt-5"> 1533 @Translate("ChooseProduct", "V&aelig;lg produkt") 1534 </p> 1535 <div class="row align-items-end" data-bind="foreach: FilteredVariants"> 1536 <div class="col-12 col-sm-6 col-md-3 mb-3"> 1537 <a class="color-black no-underline" data-bind="attr: { href: Link }"> 1538 <p class="fs0 font-weight-bold m-0" data-bind="text: Name"></p> 1539 <img class="img-fluid box-shadow my-1" data-bind="attr: { src: Image }" /> 1540 <div class="d-flex justify-content-center mt-2"> 1541 <div class="btn btn-primary">@Translate("VariantChooseProduct", "V&aelig;lg")</div> 1542 </div> 1543 </a> 1544 </div> 1545 </div> 1546 <div data-bind="visible: FilteredVariants().length == 0"> 1547 <p class="font-weight-bold mt-3 fs3">@Translate("VariantsNoResults", "Filtreringen gav ingen resultater")</p> 1548 </div> 1549 </div> 1550 </div> 1551 </div> 1552 1553 @SnippetStart("DataLayerOverwrites") 1554 <script> 1555 ecomm_pagetype = "Product"; 1556 ecomm_totalvalue = @GetString("Ecom:Product.Price.Price").Replace(".","").Replace(",","."); 1557 ecomm_prodid = "@GetString("Ecom:Product.ID")"; 1558 </script> 1559 @SnippetEnd("DataLayerOverwrites") 1560 1561 <script> 1562 var dataLayer = window.dataLayer || []; 1563 dataLayer.push({ 1564 'event': 'product', 1565 'ecommerce': { 1566 'detail': { 1567 'actionField': { 1568 'list': '@DataLayerParentGroups' 1569 }, 1570 'products': [{ 1571 'id': '@ProductID', 1572 'name': '@ProductName', 1573 'image': '@OgImage', 1574 'brand': '@BrandName', 1575 'variant': '@CurrentVariantName', 1576 'category': '@DataLayerParentGroup', 1577 'price': '@DataLayerPrice' 1578 }] 1579 } 1580 }, 1581 'page': { 1582 'type': 'product', 1583 'environment': 'production' 1584 } 1585 }); 1586 </script> 1587