test
Error executing template "Designs/Rapido/eCom/Product/Product.cshtml"
System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
Parameter name: length
   at System.String.Substring(Int32 startIndex, Int32 length)
   at CompiledRazorTemplates.Dynamic.RazorEngine_a6b21678d7594f98b9d69aec46484b08.Execute() in D:\Dynamicweb.net\Solutions\twodayco3\nordicunderlay.cloud.dynamicweb-cms.com\Files\Templates\Designs\Rapido\eCom\Product\Product.cshtml:line 2620
   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.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2 3 @using System.Web 4 @using Dynamicweb.Extensibility 5 @using Dynamicweb.Content 6 @using System 7 @using System.IO 8 @using Dynamicweb.Core 9 @using System.Web 10 @using System.Globalization 11 @using System.Text.RegularExpressions 12 @using System.Web.UI.HtmlControls 13 @using Dynamicweb.Rapido.Blocks 14 @using Dynamicweb.Ecommerce 15 16 @functions { 17 List<LoopItem> downloadDocuments = new List<LoopItem>(); 18 List<LoopItem> customFieldsWithValue = new List<LoopItem>(); 19 //downloadDocuments variable, will be defined in Fields.cshtml and used in ProductAssets.cshtml 20 21 BlocksPage productsPage = BlocksPage.GetBlockPage("Product"); 22 23 public static string ToPascalCase(string str) 24 { 25 return CultureInfo.InvariantCulture.TextInfo 26 .ToTitleCase(str.ToLowerInvariant()) 27 .Replace("-", "") 28 .Replace("_", "") 29 .Replace(" ", ""); 30 } 31 } 32 33 @{ 34 string productBlocksPosition = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "thumbs-image-info"; 35 bool productInfoOnTheRight = productBlocksPosition.LastIndexOf("info") == productBlocksPosition.Length - 4; 36 37 Block productTop = new Block() 38 { 39 Id = "Top", 40 SortId = 10, 41 SkipRenderBlocksList = true, 42 Template = RenderProductTop() 43 }; 44 productsPage.Add(productTop); 45 46 Block productMainInfo = new Block() 47 { 48 Id = "MainInformation", 49 SortId = productInfoOnTheRight ? 20 : 10, 50 Design = new Design 51 { 52 Size = "auto", 53 RenderType = RenderType.Column 54 } 55 }; 56 productsPage.Add("Top", productMainInfo); 57 58 //Optional mini tabs block 59 Block miniTabsBlock = new Block() 60 { 61 Id = "MiniTabs", 62 SortId = 40, 63 Template = RenderProductMiniTabs(), 64 SkipRenderBlocksList = true 65 }; 66 productsPage.Add("MainInformation", miniTabsBlock); 67 //----- 68 69 Block productTabsBlock = new Block() 70 { 71 Id = "Tabs", 72 SortId = 30, 73 Template = RenderProductTabs(), 74 SkipRenderBlocksList = true 75 }; 76 productsPage.Add(productTabsBlock); 77 78 Block productDetailsBlock = new Block() 79 { 80 Id = "Section", 81 SortId = 30 82 }; 83 productsPage.Add(productDetailsBlock); 84 85 Block productSnippetsBlock = new Block() 86 { 87 Id = "Snippets", 88 SortId = 40 89 }; 90 productsPage.Add(productSnippetsBlock); 91 } 92 93 @* Include the required Grid builder (Contains the methods @RenderBlockList and @RenderBlock) *@ 94 @using System.Text.RegularExpressions 95 @using System.Collections.Generic 96 @using System.Reflection 97 @using System.Web.UI.HtmlControls 98 @using Dynamicweb.Rapido.Blocks.Components 99 @using Dynamicweb.Rapido.Blocks.Components.Articles 100 @using Dynamicweb.Rapido.Blocks.Components.Documentation 101 @using Dynamicweb.Rapido.Blocks 102 103 104 @*--- START: Base block renderers ---*@ 105 106 @helper RenderBlockList(List<Block> blocks) 107 { 108 blocks = blocks.OrderBy(item => item.SortId).ToList(); 109 110 foreach (Block item in blocks) 111 { 112 <!-- START: @item.Id --> 113 114 if (item.Design == null) 115 { 116 @RenderBlock(item) 117 } 118 else if (item.Design.RenderType == RenderType.None) { 119 string cssClass = item.Design.CssClass != null ? item.Design.CssClass : ""; 120 121 <div class="@cssClass dw-mod"> 122 @RenderBlock(item) 123 </div> 124 } 125 else if (item.Design.RenderType != RenderType.Hide) 126 { 127 string cssClass = item.Design.CssClass != null ? item.Design.CssClass : ""; 128 129 if (!item.SkipRenderBlocksList) { 130 if (item.Design.RenderType == RenderType.Row) 131 { 132 <div class="grid grid--align-content-start @cssClass dw-mod" id="Block__@item.Id"> 133 @RenderBlock(item) 134 </div> 135 } 136 137 if (item.Design.RenderType == RenderType.Column) 138 { 139 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 140 string size = item.Design.Size ?? "12"; 141 size = Regex.IsMatch(size, @"\d") ? "md-" + item.Design.Size : item.Design.Size; 142 143 <div class="grid__col-lg-@item.Design.Size grid__col-md-@item.Design.Size grid__col-sm-12 grid__col-xs-12 @hidePadding @cssClass dw-mod" id="Block__@item.Id"> 144 @RenderBlock(item) 145 </div> 146 } 147 148 if (item.Design.RenderType == RenderType.Table) 149 { 150 <table class="table @cssClass dw-mod" id="Block__@item.Id"> 151 @RenderBlock(item) 152 </table> 153 } 154 155 if (item.Design.RenderType == RenderType.TableRow) 156 { 157 <tr class="@cssClass dw-mod" id="Block__@item.Id"> 158 @RenderBlock(item) 159 </tr> 160 } 161 162 if (item.Design.RenderType == RenderType.TableColumn) 163 { 164 <td class="@cssClass dw-mod" id="Block__@item.Id"> 165 @RenderBlock(item) 166 </td> 167 } 168 169 if (item.Design.RenderType == RenderType.CardHeader) 170 { 171 <div class="card-header @cssClass dw-mod"> 172 @RenderBlock(item) 173 </div> 174 } 175 176 if (item.Design.RenderType == RenderType.CardBody) 177 { 178 <div class="card @cssClass dw-mod"> 179 @RenderBlock(item) 180 </div> 181 } 182 183 if (item.Design.RenderType == RenderType.CardFooter) 184 { 185 <div class="card-footer @cssClass dw-mod"> 186 @RenderBlock(item) 187 </div> 188 } 189 } 190 else 191 { 192 @RenderBlock(item) 193 } 194 } 195 196 <!-- END: @item.Id --> 197 } 198 } 199 200 @helper RenderBlock(Block item) 201 { 202 if (item.Template != null) 203 { 204 @BlocksPage.RenderTemplate(item.Template) 205 } 206 207 if (item.Component != null) 208 { 209 string methodName = item.Component.HelperName; 210 dynamic[] methodParameters = new dynamic[1]; 211 methodParameters[0] = item.Component; 212 Type methodType = this.GetType(); 213 MethodInfo generalMethod = methodType.GetMethod(methodName); 214 215 if (generalMethod != null) { 216 @generalMethod.Invoke(this, methodParameters).ToString(); 217 } else { 218 throw new Exception(item.Component.GetType().Name + " method '" + methodName +"' could not be invoked"); 219 } 220 } 221 222 if (item.BlocksList.Count > 0 && !item.SkipRenderBlocksList) 223 { 224 @RenderBlockList(item.BlocksList) 225 } 226 } 227 228 @*--- END: Base block renderers ---*@ 229 230 231 <style type="text/css"> 232 .product__description, .product__description p, .product__description span, .product__top .introduction-text > * { 233 font-family: 'Montserrat', sans-serif !important; 234 font-size: 1.47rem !important; 235 font-weight: 400 !important; 236 line-height: 1.6 !important; 237 } 238 .product__description.center-container.dw-mod { column-count:2; } 239 240 .product__top .introduction-text > * { color:#0085ca !important;} 241 242 .longdesc_container { overflow-y: hidden; position: relative; transition: all 300ms; } 243 .longdesc_200 { height: 200px; } 244 .longdesc_200:after { 245 transition: all 500ms; 246 position: absolute; top: 0; left: 0; width: 100%; height: 100%; content: ''; 247 /* Permalink - use to edit and share this gradient: https://colorzilla.com/gradient-editor/#7db9e8+0,f4f4f4+100&0+0,0+64,1+100 */ 248 background: -moz-linear-gradient(top, rgba(125,185,232,0) 0%, rgba(201,223,240,0) 64%, rgba(255,255,255,1) 100%); /* FF3.6-15 */ 249 background: -webkit-linear-gradient(top, rgba(125,185,232,0) 0%,rgba(201,223,240,0) 64%,rgba(255,255,255,1) 100%); /* Chrome10-25,Safari5.1-6 */ 250 background: linear-gradient(to bottom, rgba(125,185,232,0) 0%,rgba(201,223,240,0) 64%,rgba(255,255,255,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ 251 filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#007db9e8', endColorstr='#ffffff',GradientType=0 ); /* IE6-9 */ 252 } 253 .introduction-text > .longdesc_expand { 254 transition: all 200ms; 255 margin:15px auto 0px auto; 256 display: table; padding: 7px 30px; background-color: #333; color: #fff !important; cursor: pointer; text-transform: uppercase; border-radius: 2px; 257 text-align: center; 258 } 259 .longdesc_expand:hover { background-color:#000; } 260 </style> 261 262 @* Include the Blocks for the page *@ 263 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 264 @using Dynamicweb.Core 265 @using System 266 @using System.Web 267 @using System.Collections.Generic 268 @using Dynamicweb.Rapido.Blocks 269 270 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 271 @using System.Linq; 272 273 @functions{ 274 public class Sticker 275 { 276 public string className { get; set; } 277 public string text { get; set; } 278 } 279 280 public class StickersContainer 281 { 282 public string position { get; set; } 283 public List<Sticker> Stickers { get; set; } 284 } 285 286 public void AddSticker(List<StickersContainer> list, Sticker sticker, string stickerPosition) 287 { 288 StickersContainer stickersContainerTemp; 289 if (string.IsNullOrEmpty(stickerPosition)) 290 { 291 stickerPosition = "top-left"; 292 } 293 stickersContainerTemp = list.FirstOrDefault(stickersContainer => stickersContainer.position == stickerPosition); 294 if (stickersContainerTemp == null) 295 { 296 stickersContainerTemp = new StickersContainer() 297 { 298 position = stickerPosition, 299 Stickers = new List<Sticker>() 300 }; 301 list.Add(stickersContainerTemp); 302 } 303 stickersContainerTemp.Stickers.Add(sticker); 304 } 305 306 public List<StickersContainer> GetStickersContainersList(List<LoopItem> discountsLoop, double discountPrice, double price, DateTime createdDate, string customStickerValue) 307 { 308 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 309 bool isSaleStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetBoolean("Enable"); 310 bool isNewsStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetBoolean("Enable"); 311 bool isCustomStickersEnabled = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetBoolean("Enable"); 312 313 List<StickersContainer> resultList = new List<StickersContainer>(); 314 315 if (!pointShopOnly && isSaleStickersEnabled) 316 { 317 string contentType = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetString("ContentType"); 318 contentType = !string.IsNullOrEmpty(contentType) ? contentType : "Name"; 319 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 320 Sticker saleSticker = new Sticker(); 321 saleSticker.className = "stickers-container__tag--sale"; 322 323 switch (contentType) 324 { 325 case "Name": 326 foreach (LoopItem discount in discountsLoop) 327 { 328 saleSticker.text = discount.GetString("Ecom:Product.Discount.Name"); 329 } 330 break; 331 case "Amount": 332 if (discountsLoop.Count > 0) 333 { 334 saleSticker.text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, discountPrice - price); 335 } 336 break; 337 case "Percents": 338 double percents = 0; 339 foreach (LoopItem discount in discountsLoop) 340 { 341 percents += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 342 } 343 if (percents > 0) 344 { 345 saleSticker.text = Math.Round(percents, 0) + "%"; 346 } 347 break; 348 case "Amount+and+percents": 349 double amount = 0; 350 double percent = 0; 351 foreach (LoopItem discount in discountsLoop) 352 { 353 if (discount.GetString("Ecom:Product.Discount.Type") == "PERCENT") 354 { 355 percent += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 356 } 357 else if (discount.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 358 { 359 amount += discount.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 360 } 361 } 362 363 if (percent > 0) 364 { 365 saleSticker.text = percent + "%"; 366 } 367 else if (amount > 0) 368 { 369 saleSticker.text = "-" + Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 370 } 371 break; 372 default: 373 if (discountsLoop.Count > 0) 374 { 375 saleSticker.text = Translate("Sale!"); 376 } 377 break; 378 } 379 380 string saleStickerPosition = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetList("Position") != null ? 381 Pageview.AreaSettings.GetItem("Ecommerce").GetItem("SaleSticker").GetList("Position").SelectedValue : "topLeft"; 382 if (!string.IsNullOrEmpty(saleSticker.text)) { 383 AddSticker(resultList, saleSticker, saleStickerPosition); 384 } 385 } 386 387 if (!pointShopOnly && isNewsStickersEnabled && createdDate.AddDays(Converter.ToDouble(Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetString("Expiration"))) > DateTime.Now) 388 { 389 Sticker newSticker = new Sticker(); 390 newSticker.className = "stickers-container__tag--new"; 391 newSticker.text = Translate("New!"); 392 string newStickerPosition = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetList("Position") != null ? 393 Pageview.AreaSettings.GetItem("Ecommerce").GetItem("NewSticker").GetList("Position").SelectedValue : "topLeft"; 394 AddSticker(resultList, newSticker, newStickerPosition); 395 } 396 397 if (!pointShopOnly && isCustomStickersEnabled && !string.IsNullOrEmpty(customStickerValue)) 398 { 399 Sticker customSticker = new Sticker(); 400 customSticker.className = "stickers-container__tag--custom"; 401 customSticker.text = customStickerValue; 402 string customStickerPosition = Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetList("Position") != null ? 403 Pageview.AreaSettings.GetItem("Ecommerce").GetItem("CustomSticker").GetList("Position").SelectedValue : "topLeft"; 404 AddSticker(resultList, customSticker, customStickerPosition); 405 } 406 407 return resultList; 408 } 409 } 410 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 411 412 413 @* 414 This is a temporary fallback for the DefaultImage. The image pattern MUST be set up like this: 415 416 ImageSmall = /{ProductNumber}.jpg 417 ImageMedium = /{ProductNumber}{VariantOptionLevel1}.jpg 418 ImageLarge = /{ProductNumber}{VariantComboName}.jpg 419 420 In addition to the ImageDefault setting 421 *@ 422 423 @functions { 424 public string GetProductImage(LoopItem productObject = null) 425 { 426 string theImage = ""; 427 428 if (productObject == null) { 429 theImage = GetString("Ecom:Product.ImageDefault.Default.Clean"); 430 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageLarge.Clean") : theImage; 431 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageMedium.Clean") : theImage; 432 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageSmall.Clean") : theImage; 433 theImage = String.IsNullOrEmpty(theImage) ? GetString("Ecom:Product.ImageLarge.Default.Clean") : theImage; 434 } else { 435 theImage = productObject.GetString("Ecom:Product.ImageDefault.Default.Clean"); 436 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageLarge.Clean") : theImage; 437 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageMedium.Clean") : theImage; 438 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageSmall.Clean") : theImage; 439 theImage = String.IsNullOrEmpty(theImage) ? productObject.GetString("Ecom:Product.ImageLarge.Default.Clean") : theImage; 440 } 441 442 return theImage; 443 } 444 } 445 446 @functions { 447 BlocksPage mainImagePage = BlocksPage.GetBlockPage("Product"); 448 bool showThumbs; 449 bool thumbsOnTheSide; 450 } 451 452 @{ 453 string imageBlockWidth = Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("TopLayout").SelectedValue : "6"; 454 string blocksPosition = Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ImageSectionPosition").SelectedValue : "thumbs-image-info"; 455 bool infoOnTheRight = blocksPosition.LastIndexOf("info") == blocksPosition.Length - 4; 456 showThumbs = blocksPosition.IndexOf("thumbs") != -1; 457 thumbsOnTheSide = showThumbs && blocksPosition.IndexOf("thumbsBottom") == -1; 458 bool thumbsOnTheLeft = blocksPosition.IndexOf("image") > blocksPosition.IndexOf("thumbs"); 459 //imageBlockWidth = imageBlockPosition == "left-left" || imageBlockPosition == "left-right" ? Converter.ToString(12 - Converter.ToInt32(imageBlockWidth)) : imageBlockWidth; 460 461 Block mainImageBlock = new Block() 462 { 463 Id = "MainImage", 464 SortId = infoOnTheRight ? 10 : 20, 465 Design = new Design 466 { 467 Size = imageBlockWidth, 468 RenderType = RenderType.Column 469 }, 470 BlocksList = new List<Block> 471 { 472 new Block { 473 Id = "MainImageRow", 474 SortId = 10, 475 Design = new Design 476 { 477 RenderType = RenderType.Row 478 }, 479 BlocksList = new List<Block> 480 { 481 new Block 482 { 483 Id = "Carousel", 484 SortId = 10, 485 Template = RenderThumbnails(), 486 Design = new Design 487 { 488 Size = thumbsOnTheSide ? "2" : "12", 489 RenderType = RenderType.Column, 490 CssClass = thumbsOnTheSide ? "u-hidden-xxs" : "" 491 } 492 } 493 } 494 } 495 } 496 }; 497 mainImagePage.Add("Top", mainImageBlock); 498 499 mainImagePage.Add("MainImageRow", 500 new Block() 501 { 502 Id = "ProductImageModal", 503 SortId = 0, 504 Template = RenderModal() 505 }); 506 507 if (showThumbs) 508 { 509 mainImagePage.Add("MainImageRow", 510 new Block 511 { 512 Id = "Image", 513 SortId = thumbsOnTheLeft ? 20 : 0, 514 Template = RenderImage(), 515 Design = new Design 516 { 517 Size = thumbsOnTheSide ? "auto" : "12", 518 RenderType = RenderType.Column 519 } 520 }); 521 } 522 } 523 524 @helper RenderModal() 525 { 526 <!-- Trigger for the gallery modal --> 527 <input type="checkbox" id="GalleryModalTrigger" class="modal-trigger" /> 528 529 if (!string.IsNullOrEmpty(GetString("Ecom:Product.ImageLarge.Default.Clean"))) 530 { 531 <!-- Gallery modal --> 532 <div class="modal-container"> 533 <label for="GalleryModalTrigger" id="GalleryModalOverlay" class="modal-overlay"></label> 534 <div class="modal" id="GalleryModal"> 535 <div class="modal__body modal__body--full"> 536 @RenderCarousel("modalCarousel", 1, "horizontal", 3, true) 537 <label class="modal__close-btn dw-mod" for="GalleryModalTrigger"></label> 538 </div> 539 </div> 540 </div> 541 } 542 } 543 544 @helper RenderStickers() 545 { 546 List<StickersContainer> StickersContainers = GetStickersContainersList( 547 GetLoop("ProductDiscounts"), 548 GetDouble("Ecom:Product.Discount.Price.Price"), 549 GetDouble("Ecom:Product.Price.Price"), 550 GetDate("Ecom:Product.Created"), 551 GetString("Ecom:Product:Field.CustomSticker.Value") 552 ); 553 554 foreach (StickersContainer stickersContainer in StickersContainers) 555 { 556 <div class="stickers-container stickers-container--@(stickersContainer.position) dw-mod"> 557 @foreach (Sticker sticker in stickersContainer.Stickers) 558 { 559 <div class="stickers-container__tag @sticker.className dw-mod">@sticker.text</div> 560 } 561 </div> 562 } 563 } 564 565 @helper RenderImage() 566 { 567 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&amp;height=800&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 568 string productId = GetString("Ecom:Product.ID"); 569 string image = GetProductImage(); 570 571 <label for="GalleryModalTrigger" class="product__image-container u-position-relative"> 572 <img class="product__image-container__image dw-mod b-lazy" src="/Files/Images/placeholder.gif" data-src="@imagePrefix@image" alt="@GetString("Ecom:Product.Name")" id="Image_@productId" data-for="FullImage" data-number="0" onclick="modalCarousel.GoToSlide('modalCarousel', this.getAttribute('data-number'))" /> 573 @RenderStickers() 574 </label> 575 } 576 577 @helper RenderThumbnails() 578 { 579 <div class="@(showThumbs ? "product__thumbs" : "") dw-mod"> 580 @RenderCarousel( 581 "productCarousel", 582 !showThumbs ? 1 : 5, 583 thumbsOnTheSide ? "vertical" : "horizontal", 584 !showThumbs ? 3 : 2 585 ) 586 @if (!showThumbs) 587 { 588 @RenderStickers() 589 } 590 </div> 591 } 592 593 @helper RenderCarousel(string id, int slidesInView, string direction, int preloaderSize, bool isModal = false) 594 { 595 <div class="carousel dw-mod" id="@id"> 596 <div class="thumb-list carousel__container @(slidesInView != 1 ? "carousel__container--hidden" : "") js-carousel-slides dw-mod"> 597 @*Main image thumb*@ 598 @RenderProductImage(GetProductImage(), slidesInView == 1, isModal ? "modal--full__img" : "", true, isModal) 599 600 @foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 601 { 602 if (!string.IsNullOrEmpty(alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"))) 603 { 604 @RenderProductImage(alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"), slidesInView == 1, isModal ? "modal--full__img" : "", false, isModal) 605 } 606 } 607 608 @foreach (LoopItem detail in GetLoop("Details")) 609 { 610 if (!string.IsNullOrEmpty(detail.GetString("Ecom:Product:Detail.Image.Clean"))) 611 { 612 string ext = Path.GetExtension(detail.GetString("Ecom:Product:Detail.Image.Clean")).ToLower(); 613 if (ext == ".jpg" || ext == ".jpeg" || ext == ".gif" || ext == ".png") 614 { 615 @RenderProductImage(detail.GetString("Ecom:Product:Detail.Image.Clean"), slidesInView == 1, isModal ? "modal--full__img" : "", false, isModal) 616 } 617 } 618 } 619 </div> 620 621 <script> 622 document.addEventListener("DOMContentLoaded", function () { 623 @id = new CarouselModule('#@id', { 624 slidesInView: @slidesInView, 625 direction: "@direction", 626 preloaderSize: @preloaderSize, 627 showCounter: @isModal.ToString().ToLower() 628 }); 629 }); 630 </script> 631 </div> 632 } 633 634 @helper RenderProductImage(string image, bool isBig, string cssClass = "", bool isActive = false, bool isModal = false) 635 { 636 string productId = GetString("Ecom:Product.ID"); 637 string thumbPrefix = "/Admin/Public/GetImage.ashx?width=200&amp;height=200&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 638 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&amp;height=800&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image="; 639 640 <div class="carousel__slide dw-mod"> 641 @if (isModal) 642 { 643 <img src="@image" class="@cssClass" alt="@GetString("Ecom:Product.Name")"> 644 } 645 else if (isBig) 646 { 647 <label for="GalleryModalTrigger"> 648 <img src="@imagePrefix@image" alt="@GetString("Ecom:Product.Name")" class="js-gallery @cssClass" t=d data-for="FullImage" data-image="@image" onclick="modalCarousel.GoToSlide('modalCarousel', this.closest('.carousel__slide').index());"> 649 </label> 650 } 651 else 652 { 653 <div class="thumb-list__item dw-mod js-thumb js-gallery @(isActive ? "js-thumb--active thumb-list__item--active" : "")" data-for="Image_@productId" data-image="@imagePrefix@image" onmouseover="Gallery.openImage(this)"> 654 <label for="GalleryModalTrigger"> 655 <img src="@thumbPrefix@image" alt="@GetString("Ecom:Product.Name")" class="js-gallery @cssClass" data-for="FullImage" data-image="@image" onclick="modalCarousel.GoToSlide('modalCarousel', this.closest('.carousel__slide').index());"> 656 </label> 657 </div> 658 } 659 </div> 660 } 661 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 662 @using Dynamicweb.Core 663 @using System 664 @using System.Web 665 @using System.Collections.Generic 666 @using Dynamicweb.Rapido.Blocks 667 @functions { 668 bool useFacebookPixel; 669 bool useGoogleTagManager; 670 BlocksPage mainInfoPage = BlocksPage.GetBlockPage("Product"); 671 } 672 673 @{ 674 bool mainInfoRenderVariantsAsProducts = GetInteger("Ecom:Product.VariantCount") > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); useFacebookPixel = !string.IsNullOrWhiteSpace(Pageview.AreaSettings.GetItem("Settings").GetString("FacebookPixelID")); 675 useGoogleTagManager = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("Settings").GetString("GoogleTagManagerID")); 676 bool hidePrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 677 bool hideAddToCartButton = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("hideAddToCartButton"); 678 679 Block mainInfoHeader = new Block() 680 { 681 Id = "MainInfoHeader", 682 SortId = 10, 683 Template = RenderMainInfoHeader() 684 }; 685 mainInfoPage.Add("MainInformation", mainInfoHeader); 686 687 Block mainInfoDescription = new Block() 688 { 689 Id = "ShortDescription", 690 SortId = 30, 691 Template = RenderShortDescription() 692 }; 693 mainInfoPage.Add("MainInformation", mainInfoDescription); 694 695 if (!mainInfoRenderVariantsAsProducts) 696 { 697 Block mainInfoVariants = new Block() 698 { 699 Id = "Variants", 700 SortId = 50, 701 Template = RenderMainInfoVariants() 702 }; 703 mainInfoPage.Add("MainInformation", mainInfoVariants); 704 } 705 706 Block mainInfoBOM = new Block() 707 { 708 Id = "BOM", 709 SortId = 60, 710 Template = RenderMainInfoBOM() 711 }; 712 mainInfoPage.Add("MainInformation", mainInfoBOM); 713 714 if (!mainInfoRenderVariantsAsProducts) 715 { 716 if (!hidePrice && !hideAddToCartButton) 717 { 718 Block mainInfoBuy = new Block() 719 { 720 Id = "Buy", 721 SortId = 80, 722 Template = RenderMainInfoBuy() 723 }; 724 mainInfoPage.Add("MainInformation", mainInfoBuy); 725 } 726 727 Block stockAndShipping = new Block() 728 { 729 Id = "StockAndShipping", 730 SortId = 90, 731 Template = RenderStockAndShipping() 732 }; 733 mainInfoPage.Add("MainInformation", stockAndShipping); 734 } 735 } 736 737 @helper RenderMainInfoHeader() 738 { 739 bool renderVariantsAsProducts = GetInteger("Ecom:Product.VariantCount") > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 740 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 741 string currentPrice = GetString("Ecom:Product.Discount.Price.PriceFormatted") == GetString("Ecom:Product.Price.PriceFormatted") ? GetString("Ecom:Product.Price.PriceFormatted") : GetString("Ecom:Product.Discount.Price.PriceFormatted"); 742 bool hideFavorites = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideFavoriteButton"); 743 bool hideProductNumber = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumber"); 744 745 bool useFontAwesomePro = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetBoolean("UseFontAwesomePro"); 746 var selectedFavoriteIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("FavoriteIcon").SelectedValue : "star"; 747 string favoriteIcon = "fas fa-" + selectedFavoriteIcon; 748 string favoriteOutlineIcon = "far fa-" + selectedFavoriteIcon; 749 750 string varcomboname = GetString("Ecom:Product.SelectedVariantComboName"); 751 752 //fix for displaying variant name - don't remove next line! 753 GetLoop("VariantCombinations"); 754 755 <div> 756 <div class="u-pull--left product__title dw-mod"> 757 <h1 class="u-no-margin">@GetString("Ecom:Product.Name") </h1> 758 @if(!string.IsNullOrEmpty(varcomboname)){ 759 <h2>@varcomboname</h2> 760 } 761 762 763 @if (!hideProductNumber) 764 { 765 <div class="item-number dw-mod">@GetString("Ecom:Product.Number")</div> 766 } 767 </div> 768 <div class="u-pull--right"> 769 @if (!hideFavorites && Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")) && !renderVariantsAsProducts) 770 { 771 string favoriteId = "Favorite" + GetString("Ecom:Product.ID"); 772 <div id="@favoriteId" class="favorites favorites--md u-pull--right js-favorite-btn dw-mod"> 773 <div> 774 @{ 775 string favorite = GetBoolean("Ecom:Product.IsProductInFavoriteList") ? favoriteIcon : favoriteOutlineIcon; 776 string AddToWishlist = "fbq('track', 'AddToWishlist', {" + 777 "content_name: '" + GetString("Ecom:Product.Name") + "'," + 778 "content_ids: ['" + GetString("Ecom:Product.Number") + "']," + 779 "value: " + GetDouble("Ecom:Product.Price.Price") + "," + 780 "currency: '" + GetString("Ecom:Product.Price.Currency.Code") + "'" + 781 "});"; 782 } 783 <label for="FavoriteTrigger"><i class="@favorite fa-1_5x"></i></label> 784 </div> 785 <input type="checkbox" id="FavoriteTrigger" class="dropdown-trigger" /> 786 787 <div class="dropdown"> 788 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 789 <ul class="list list--clean dw-mod"> 790 @if (GetLoop("CustomerCenter.ListTypes").Count > 0) 791 { 792 foreach (LoopItem listType in GetLoop("CustomerCenter.ListTypes")) 793 { 794 foreach (LoopItem list in listType.GetLoop("CustomerCenter.ProductLists")) 795 { 796 string favLinkType = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? list.GetString("Ecom:Product.RemoveFromThisList") : list.GetString("Ecom:Product.AddToThisListAction"); 797 string isInListIcon = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? favoriteIcon : favoriteOutlineIcon; 798 <li> 799 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(list.GetString("Ecom:Product.List.IsProductInThisList") != "True" && useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon"></i> @list.GetValue("Ecom:CustomerCenter.List.Name")</a> 800 </li> 801 } 802 } 803 } 804 else 805 { 806 string favLinkType = GetString("Ecom:Product.AddToFavorites") + "&CCListType=0&CCCreateNewList=" + Translate("My favorites"); 807 string isInListIcon = favoriteOutlineIcon; 808 <li> 809 <a href="@favLinkType" class="list__link u-no-underline dw-mod" onclick="@(useFacebookPixel ? AddToWishlist : "")"><i class="@isInListIcon"></i> @Translate("My favorites")</a> 810 </li> 811 } 812 </ul> 813 </div> 814 <label class="dropdown-trigger-off" for="FavoriteTrigger"></label> 815 </div> 816 </div> 817 } 818 </div> 819 </div> 820 } 821 822 @helper RenderStockAndShipping() 823 { 824 bool hideStockState = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideStockState"); 825 bool hideDelivery = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideShipping"); 826 bool onlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 827 828 if (!onlyPreview && (!string.IsNullOrEmpty(GetString("Ecom:Product:Stock.Text")) || !string.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText")))) 829 { 830 string stockIcon = GetInteger("Ecom:Product.Stock") > 0 ? "stock-icon--in" : "stock-icon--not"; 831 832 <div class="product__stock-delivery dw-mod id_@(GetString("Ecom:Product.Number")) st_@(GetInteger("Ecom:Product.Stock"))"> 833 @if (!hideStockState) 834 { 835 @GetString("Ecom:Product:Stock.Text") <div class="stock-icon @stockIcon"></div> 836 } 837 838 @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText")) && !hideDelivery) 839 { 840 <span>@Translate("Shipping")</span> <span>@GetString("Ecom:Product:Stock.DeliveryText")</span> <span>@GetString("Ecom:Product:Stock.DeliveryUnit")</span> 841 } 842 </div> 843 } 844 } 845 846 @helper RenderShortDescription() 847 { 848 if (!String.IsNullOrEmpty(GetString("Ecom:Product.ShortDescription"))) 849 { 850 <div class="introduction-text" property="description" id="description"> 851 @{ 852 string tmp_desc = GetString("Ecom:Product.ShortDescription"); 853 int tmp_length = tmp_desc.Length + Regex.Matches(tmp_desc, "<br").Count * 40 + Regex.Matches(tmp_desc, "<p>").Count * 75; 854 855 } 856 @if(tmp_length > 1050){ 857 <div class="longdesc_container longdesc_200" > 858 @tmp_desc 859 </div> 860 <div class="longdesc_expand fn_expand"> 861 Læs mere 862 </div> 863 } else { 864 @tmp_desc 865 } 866 </div> 867 } 868 } 869 870 @helper RenderMainInfoVariants() 871 { 872 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 873 string productId = GetString("Ecom:Product.ID"); 874 string variantSelection = !String.IsNullOrEmpty(HttpContext.Current.Request.QueryString.Get("variantId")) ? HttpContext.Current.Request.QueryString.Get("variantId").Replace(".", ",") : ""; 875 string hideHelpText = ""; 876 877 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 878 { 879 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 880 { 881 if (variantoption.GetBoolean("Ecom:VariantOption.Selected")) 882 { 883 hideHelpText = "u-hidden"; 884 } 885 } 886 } 887 888 if (GetLoop("VariantGroups").Count > 0) 889 { 890 var variantCombinationsObject = new List<Array>(); 891 foreach (LoopItem variantcomb in GetLoop("VariantStockCombinations")) 892 { 893 string[] combinations = variantcomb.GetString("Ecom:VariantStockCombination.VariantID").Split('.'); 894 variantCombinationsObject.Add(combinations); 895 } 896 897 string combinationsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantCombinationsObject).Replace("\"", "\'"); 898 899 var variantGroupsObject = new List<List<String>>(); 900 foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 901 { 902 var variantsObject = new List<String>(); 903 foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 904 { 905 variantsObject.Add(variantOption.GetString("Ecom:VariantOption.ID")); 906 } 907 variantGroupsObject.Add(variantsObject); 908 } 909 string variantsJson = Newtonsoft.Json.JsonConvert.SerializeObject(variantGroupsObject).Replace("\"", "\'"); 910 string productGroupId = HttpContext.Current.Request["GroupId"]; 911 <div> 912 <div class="js-variants" data-total-variant-groups="@GetLoop("VariantGroups").Count" data-combinations="@combinationsJson" data-variants="@variantsJson" data-variant-selections="@variantSelection" data-selection-complete="UpdatePage" data-page-id="@pageId" data-product-id="@productId" data-group-id="@productGroupId"> 913 @foreach (LoopItem variantGroup in GetLoop("VariantGroups")) 914 { 915 string groupId = variantGroup.GetString("Ecom:VariantGroup.ID"); 916 917 <div> 918 <div class="product__variant-group-name u-bold dw-mod">@variantGroup.GetString("Ecom:VariantGroup.Name")</div> 919 <div class="u-margin-top"> 920 @foreach (LoopItem variantOption in variantGroup.GetLoop("VariantAvailableOptions")) 921 { 922 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 923 string color = !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Colorcode")) ? variantOption.GetString("Ecom:VariantOption.Colorcode") : null; 924 color = color == null && !String.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.Color")) ? variantOption.GetString("Ecom:VariantOption.Color") : color; 925 926 if (!string.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.ImgSmall.Clean"))) 927 { 928 string variantImage = "/Admin/Public/GetImage.ashx?width=100&amp;height=50&amp;crop=5&amp;Compression=75&amp;image=/Images/" + variantOption.GetString("Ecom: VariantOption.ImgSmall.Clean"); 929 <img data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" src="@variantImage" onclick="MatchVariants.SelectThis(event)" alt="@variantOption.GetString("Ecom:VariantOption.Name")" title="@variantOption.GetString("Ecom:VariantOption.Name")" class="btn btn--tag @selected js-variant-option" data-check="@selected" /> 930 } 931 else if (!String.IsNullOrEmpty(color)) 932 { 933 <button type="button" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" onclick="MatchVariants.SelectThis(event)" class="btn btn--colorbox u-margin-right @selected js-variant-option" data-check="@selected" style="background-color: @color"></button> 934 } 935 else 936 { 937 <button type="button" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-group="@groupId" onclick="MatchVariants.SelectThis(event)" class="btn btn--tag @selected js-variant-option" data-check="@selected">@variantOption.GetString("Ecom:VariantOption.Name")</button> 938 } 939 } 940 </div> 941 </div> 942 } 943 </div> 944 <small class="js-help-text help-text @hideHelpText">@Translate("Please select variant!")</small> 945 </div> 946 } 947 } 948 949 @helper RenderMainInfoBOM() 950 { 951 if (GetLoop("BOMProducts").Count > 0) 952 { 953 <h2 class="section-title">@Translate("Including products")</h2> 954 foreach (LoopItem BOMProductItem in GetLoop("BOMProducts")) 955 { 956 string link = "/" + BOMProductItem.GetString("Ecom:Product.LinkGroup.Clean") + (!String.IsNullOrEmpty(BOMProductItem.GetString("Ecom:Product.VariantID")) ? "&VariantID=" + BOMProductItem.GetString("Ecom:Product.VariantID") : ""); 957 <div class="grid__col--border grid"> 958 <div class="grid__cell grid__cell--align-middle-left"> 959 <a href="@link" class="u-pull--left u-margin-right"> 960 <img class="b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=50&image=@GetProductImage(BOMProductItem)&Compression=99" alt="@BOMProductItem.GetString("Ecom:Product.Name")" /> 961 </a> 962 <a href="@link">@BOMProductItem.GetString("Ecom:Product.Name")</a> 963 </div> 964 </div> 965 } 966 } 967 } 968 969 @helper RenderMainInfoBuy() 970 { 971 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 972 string variantId = HttpContext.Current.Request.QueryString.Get("variantId"); 973 string productId = GetString("Ecom:Product.ID"); 974 string feedId = pageId + "&ProductID=" + productId + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 975 976 <div class="product__price-actions js-handlebars-root dw-mod" id="PriceAndActions" data-template="PricesAndActionsTemplate" data-json-feed="/Default.aspx?ID=@feedId" data-preloader="minimal"></div> 977 <input type="hidden" value="@GetString("Ecom:Product.VariantID.Extented")" name="Variant" id="Variant_@GetString("Ecom:Product.ID")" /> 978 @RenderMainInfoBuyScripts() 979 } 980 981 @helper RenderMainInfoBuyScripts() 982 { 983 bool isUser = false; if(Pageview.User != null){isUser = true;} 984 bool hidePrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HidePrice"); 985 bool hideAddToCartButton = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("hideAddToCartButton"); 986 bool onlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 987 bool pointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 988 string variantId = HttpContext.Current.Request.QueryString.Get("variantId") ?? ""; 989 string feedId = GetGlobalValue("Global:Page.ID").ToString() + "&ProductID=" + GetString("Ecom:Product.ID") + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 990 string cartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 991 bool showVATPrice = Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("ShowBothPricesWithWithoutVAT"); 992 bool isPricesWithVATEnabled = Converter.ToBoolean(Pageview.Area.EcomPricesWithVat); 993 994 @* Handlebars templates *@ 995 <script id="PricesAndActionsTemplate" type="text/x-template"> 996 {{#.}} 997 @if (!onlyPreview) 998 { 999 if (!hidePrice) 1000 { 1001 <div class="product__price-actions__price dw-mod u-margin-bottom--lg"> 1002 @if (pointShopOnly) 1003 { 1004 <text> 1005 {{#if havePointPrice}} 1006 <div class="price price--product-page dw-mod">{{points}} @Translate("points")</div> 1007 {{else}} 1008 @Translate("Not available") 1009 {{/if}} 1010 </text> 1011 } 1012 else 1013 { 1014 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 1015 if(isUser){ 1016 <div class="price price--product-page dw-mod">{{priceWithoutVAT}}</div> 1017 }else{ 1018 <div class="price price--product-page dw-mod">{{price}}</div> 1019 } 1020 if (showVATPrice && isUser) 1021 { 1022 <small class="vat-price vat-price--product-page u-margin-top dw-mod"> 1023 @if (!isPricesWithVATEnabled) 1024 { 1025 @Translate("excl. VAT") <text>({{priceWithoutVAT}})</text> 1026 } 1027 else 1028 { 1029 @Translate("incl. VAT") <text>({{priceWithVAT}})</text> 1030 } 1031 </small> 1032 } 1033 } 1034 </div> 1035 } 1036 if (!hideAddToCartButton) 1037 { 1038 <div class="buttons-collection buttons-collection--right product__price-actions__actions dw-mod"> 1039 <input type="checkbox" id="UnitOptions_{{id}}" class="dropdown-trigger" /> 1040 <div class="dropdown u-w150px u-w80px--xs use-btn-primary-height dw-mod {{hasUnits}}"> 1041 <label class="dropdown__header dropdown__btn dw-mod" for="UnitOptions_{{id}}">{{unitName}}</label> 1042 <div id="unitOptions" class="dropdown__content dw-mod"> 1043 {{#unitOptions}} 1044 {{>UnitOption}} 1045 {{/unitOptions}} 1046 </div> 1047 <label class="dropdown-trigger-off" for="UnitOptions_{{id}}"></label> 1048 </div> 1049 <input type="hidden" value="{{unitId}}" name="Unit" id="Unit_{{id}}" /> 1050 @if (pointShopOnly) 1051 { 1052 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed u-no-margin dw-mod js-cart-btn {{disabledBuyButton}} {{#unless canBePurchasedWithPoints}}js-stay-disabled{{/unless}}" name="CartCmd" value="addWithPoints" 1053 onclick="Cart.AddToCart(event, { 1054 id: '{{productId}}', 1055 variantId: '{{variantid}}', 1056 unitId: '{{unitId}}', 1057 quantity: 1, 1058 buyForPoints: true, 1059 productInfo: {{productInfo}} 1060 }); {{facebookPixelAction}}"> 1061 <i class="@cartIcon"></i><span class="u-hidden-xs u-hidden-xxs"> @Translate("Buy with points")</span> 1062 </button> 1063 <text> 1064 {{#unless canBePurchasedWithPoints}} 1065 {{#if havePointPrice}} 1066 <small class="help-text u-no-margin u-margin-top">@Translate("Not enough points to buy this")</small> 1067 {{/if}} 1068 {{/unless}} 1069 </text> 1070 } 1071 else 1072 { 1073 <input type="number" class="product__quantity-selector u-w70px use-btn-primary-height dw-mod" id="Quantity_{{id}}" name="Quantity" value="1" min="1"> 1074 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed u-no-margin dw-mod js-cart-btn" name="submit" 1075 onclick="Cart.AddToCart(event, { 1076 id: '{{productId}}', 1077 variantId: '{{variantid}}', 1078 unitId: '{{unitId}}', 1079 quantity: document.getElementById('Quantity_{{id}}').value, 1080 productInfo: {{productInfo}} 1081 }); {{facebookPixelAction}}"> 1082 <i class="@cartIcon"></i><span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span> 1083 </button> 1084 } 1085 </div> 1086 if (Pageview.User != null && !pointShopOnly && Dynamicweb.Security.Licensing.LicenseManager.LicenseHasFeature("LoyaltyPoints")) 1087 { 1088 <text> 1089 {{#if canBePurchasedWithPoints}} 1090 <form method="post" role="form" class="u-no-margin u-margin-top"> 1091 <input type="hidden" name="ProductID" value="{{id}}" /> 1092 <button type="submit" class="btn btn--loyalty-points u-no-margin dw-mod pull-right u-no-margin js-cart-btn {{disabledBuyButton}}" name="CartCmd" value="addWithPoints">@Translate("Buy for") {{points}} @Translate("points")</button> 1093 </form> 1094 {{/if}} 1095 </text> 1096 } 1097 } 1098 else 1099 { 1100 <button type="button" id="CartButton_{{id}}" class="u-hidden"></button> 1101 } 1102 } 1103 {{/.}} 1104 </script> 1105 1106 <script id="Units" type="text/x-template"> 1107 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '/Default.aspx?ID=@feedId&UnitID={{value}}')">{{name}}</div> 1108 </script> 1109 1110 <script id="UnitOption" type="text/x-template"> 1111 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}&rid={{id}}')">{{name}}</div> 1112 </script> 1113 1114 1115 <script> 1116 document.addEventListener("DOMContentLoaded", function () { 1117 if (document.getElementById("PriceAndActions")) { 1118 document.getElementById("PriceAndActions").addEventListener("contentLoaded", function (event) { 1119 if (document.querySelector(".js-variants") != null) { 1120 MatchVariants.Update(document.querySelector(".js-variants"), "DoNothing"); 1121 } 1122 }); 1123 } 1124 }); 1125 </script> 1126 } 1127 1128 @if (useGoogleTagManager) 1129 { 1130 var groupObject = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(GetString("Ecom:Product.PrimaryOrFirstGroupID")); 1131 1132 <script> 1133 // Measure a view of product details. This example assumes the detail view occurs on pageload, 1134 // and also tracks a standard pageview of the details page. 1135 1136 dataLayer.push({ 1137 "ecommerce": { 1138 "detail": { 1139 "actionField": {}, // 'detail' actions have an optional list property. 1140 "products": [{ 1141 "name": "@GetString("Ecom:Product.Name")", // Name or ID is required. 1142 "id": "@GetString("Ecom:Product.ID")", 1143 "price": "@(GetDouble("Ecom:Product.Discount.Price.Price") != GetDouble("Ecom:Product.Price.Price") ? GetDouble("Ecom:Product.Discount.Price.Price") : GetDouble("Ecom:Product.Price.Price"))", 1144 "brand": "@GetString("Ecom:Product:Field.brand.Value")", 1145 "category": "@(groupObject != null ? groupObject.Name : "")", 1146 "variant": "@(!string.IsNullOrEmpty(GetString("Ecom:Product.VariantID")) ? GetString("Ecom:Product.VariantID") : GetString("Ecom:Product.VariantID.Extented"))" 1147 }] 1148 } 1149 } 1150 }); 1151 </script> 1152 } 1153 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1154 @using Dynamicweb.Core 1155 @using System 1156 @using System.Web 1157 @using System.Collections.Generic 1158 @using Dynamicweb.Rapido.Blocks 1159 @functions { 1160 BlocksPage productAssetsPage = BlocksPage.GetBlockPage("Product"); 1161 } 1162 1163 @{ 1164 string productAssetsLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("ProductAssetsLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue : "Section"; 1165 productAssetsLayout = productAssetsLayout == "Ribbon" ? "Section" : productAssetsLayout; 1166 1167 if (productAssetsLayout != "hide") 1168 { 1169 Block productAssetsBlock = new Block() 1170 { 1171 Name = productAssetsLayout != "MainInformation" ? Translate("Product assets") : "", 1172 Id = "ProductAssets", 1173 SortId = 10, 1174 @*downloadDocuments variable, declared in Product.cshtml and defined in Fields.cshtml*@ 1175 Template = RenderProductAssets(productAssetsLayout, downloadDocuments), 1176 Design = new Design 1177 { 1178 Size = "12", 1179 RenderType = RenderType.Column, 1180 HidePadding = true 1181 } 1182 }; 1183 productAssetsPage.Add(productAssetsLayout, productAssetsBlock); 1184 } 1185 } 1186 1187 @helper RenderProductAssets(string layout, List<LoopItem> documents) 1188 { 1189 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1190 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("ProductAssetsLayout").SelectedValue == "Ribbon" ? "u-padding--lg" : ""; 1191 string exportPageId = GetPageIdByNavigationTag("ProductExportFeed").ToString(); 1192 1193 //images 1194 1195 HashSet<string> images = new HashSet<string>(); 1196 1197 images.Add(GetProductImage()); 1198 1199 foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 1200 { 1201 string alt_image = alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 1202 1203 if (!string.IsNullOrEmpty(alt_image)) 1204 { 1205 images.Add(alt_image); 1206 } 1207 } 1208 1209 foreach (LoopItem detail in GetLoop("Details")) 1210 { 1211 string detail_image = detail.GetString("Ecom:Product:Detail.Image.Clean"); 1212 1213 if (!string.IsNullOrEmpty(detail_image)) 1214 { 1215 images.Add(detail_image); 1216 } 1217 } 1218 1219 <div class="product__section @ribbonClasses dw-mod"> 1220 <div class="product__description center-container @ribbonSubClasses dw-mod"> 1221 @if (layout == "Section") 1222 { 1223 <h2>@Translate("Product assets")</h2> 1224 } 1225 1226 <form action="/Default.aspx?ID=@exportPageId&ProductID=@System.Web.HttpContext.Current.Request.QueryString.Get("ProductID")&VariantID=@System.Web.HttpContext.Current.Request.QueryString.Get("VariantID")" method="post" class="u-flex grid--direction-column u-no-margin"> 1227 <div class="grid"> 1228 @if (images.Count > 0) 1229 { 1230 <div class="grid__col-md-4"> 1231 <div class="u-margin-bottom"> 1232 <input type="checkbox" class="u-no-margin form__control" id="allImages" onchange="selectAll(this)" /> 1233 <label for="allImages" class="u-bold u-inline-block">@Translate("Images") (@(images.Count))</label> 1234 </div> 1235 1236 <ul class="panel-list"> 1237 @foreach (string image in images) 1238 { 1239 @RenderPanelListItem(image) 1240 } 1241 </ul> 1242 </div> 1243 } 1244 1245 @if (documents.Count > 0) 1246 { 1247 <div class="grid__col-md-4"> 1248 <div class="u-margin-bottom"> 1249 <input type="checkbox" class="u-no-margin form__control" id="allDocuments" onchange="selectAll(this)" /> 1250 <label for="allDocuments" class="u-bold u-inline-block">@Translate("Documents") (@documents.Count)</label> 1251 </div> 1252 1253 <ul class="panel-list"> 1254 @foreach (LoopItem document in documents) 1255 { 1256 string fieldValue; 1257 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 1258 { 1259 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 1260 @RenderDocument(fieldValue) 1261 } 1262 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1263 { 1264 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 1265 @RenderDocument(fieldValue) 1266 } 1267 } 1268 </ul> 1269 </div> 1270 } 1271 <div class="grid__col-md-4"> 1272 <input id="ID" name="ID" type="hidden" value="532" /> 1273 <input id="download" name="download" type="hidden" value="true" /> 1274 <input name="siteUrl" type="hidden" value="@string.Format("{0}://{1}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host"))" /> 1275 1276 <div class="u-bold u-margin-bottom">@Translate("Export")</div> 1277 1278 <label for="exportLanguage">@Translate("Language")</label> 1279 <select id="exportLanguage" name="RequestLanguageId" class="u-full-width"> 1280 @foreach (var lang in Services.Languages.GetLanguages().OrderBy(l => l.Name)) 1281 { 1282 var selected = lang.IsDefault ? "selected" : ""; 1283 <option value="@lang.LanguageId" @selected>@lang.Name</option> 1284 } 1285 </select> 1286 1287 <label for="purpose">@Translate("Image purpose")</label> 1288 <select id="purpose" name="purpose" class="u-full-width"> 1289 <option value="Office">@Translate("Office")</option> 1290 <option value="Original">@Translate("Original")</option> 1291 <option value="Print">@Translate("Print")</option> 1292 <option value="Web">@Translate("Web")</option> 1293 </select> 1294 1295 <label for="exportFormat">@Translate("Export format")</label> 1296 <select id="exportFormat" name="format" class="u-full-width"> 1297 <option value="csv">Csv</option> 1298 <option value="json">Json</option> 1299 <option value="xml">Xml</option> 1300 </select> 1301 1302 <input type="submit" value="@Translate("Download")" class="btn btn--full btn--primary u-no-margin dw-mod" title="@Translate("Download")" /> 1303 </div> 1304 </div> 1305 </form> 1306 </div> 1307 </div> 1308 <script> 1309 function selectAll(checkbox) { 1310 Array.prototype.slice.call(checkbox.parentElement.nextElementSibling.getElementsByTagName('input')).forEach(function (input) { 1311 input.checked = checkbox.checked; 1312 }); 1313 } 1314 </script> 1315 } 1316 1317 @helper RenderPanelListItem(string imageName) 1318 { 1319 <li class="panel-list__item"> 1320 <div class="panel-list__item-check"> 1321 <input type="checkbox" name="Image_@imageName" class="u-no-margin form__control" id="Image_@imageName" /> 1322 <label for="Image_@imageName"></label> 1323 </div> 1324 <div class="panel-list__item-image"> 1325 <label for="Image_@imageName"> 1326 <img class="b-lazy flex-img" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=55&amp;height=55&amp;crop=5&amp;FillCanvas=True&amp;Compression=75&amp;image=@imageName" alt="@Path.GetFileName(imageName)"> 1327 </label> 1328 </div> 1329 <div class="panel-list__item-name"> 1330 <label for="Image_@imageName" class="u-truncate-text u-w170px"> 1331 @Path.GetFileName(imageName) 1332 </label> 1333 </div> 1334 </li> 1335 } 1336 1337 @helper RenderDocument(string fieldValue) 1338 { 1339 <li class="panel-list__item"> 1340 <div class="panel-list__item-check"> 1341 <input type="checkbox" name="Document_@fieldValue" class="u-no-margin form__control" id="Document_@fieldValue" /> 1342 <label for="Document_@fieldValue"></label> 1343 </div> 1344 <div class="panel-list__item-name"> 1345 <label for="Document_@fieldValue" class="u-truncate-text u-max-w220px"> 1346 @Path.GetFileName(fieldValue) 1347 </label> 1348 </div> 1349 </li> 1350 } 1351 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1352 @using Dynamicweb.Core 1353 @using System 1354 @using System.Web 1355 @using System.Collections.Generic 1356 @using Dynamicweb.Rapido.Blocks 1357 1358 @functions { 1359 BlocksPage productGeneratePDFPage = BlocksPage.GetBlockPage("Product"); 1360 } 1361 1362 @{ 1363 string generatePDFLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("GeneratePDFLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue : "Section"; 1364 generatePDFLayout = generatePDFLayout == "Ribbon" ? "Section" : generatePDFLayout; 1365 1366 if (GetPageIdByNavigationTag("PdfFolder") > 0 && generatePDFLayout != "hide") 1367 { 1368 Block generatePDFBlock = new Block() 1369 { 1370 Name = generatePDFLayout != "MainInformation" ? Translate("Generate PDF") : "", 1371 Id = "GeneratePDF", 1372 SortId = 10, 1373 Template = RenderGeneratePDFSection(generatePDFLayout), 1374 Design = new Design 1375 { 1376 Size = "12", 1377 RenderType = RenderType.Column, 1378 HidePadding = true 1379 } 1380 }; 1381 1382 productGeneratePDFPage.Add(generatePDFLayout, generatePDFBlock); 1383 } 1384 } 1385 1386 @helper RenderGeneratePDFSection(string layout) 1387 { 1388 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1389 ribbonClasses = layout == "Tabs" ? "u-no-padding" : ribbonClasses; 1390 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("GeneratePDFLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 1391 string exportPageId = GetPageIdByNavigationTag("ProductExportFeed").ToString(); 1392 int pdfFolderId = GetPageIdByNavigationTag("PdfFolder"); 1393 1394 <div class="product__section @ribbonClasses grid dw-mod"> 1395 <div class="dw-mod grid__col-md-4 @ribbonSubClasses"> 1396 @if (layout == "Section") { 1397 <h2>@Translate("Generate PDF")</h2> 1398 } 1399 1400 <form action="/Default.aspx?ID=@exportPageId&ProductID=@System.Web.HttpContext.Current.Request.QueryString.Get("ProductID")&VariantID=@System.Web.HttpContext.Current.Request.QueryString.Get("VariantID")&GeneratePdf=true" method="post" class="u-no-margin"> 1401 <input name="siteUrl" type="hidden" value="@string.Format("{0}://{1}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host"))" /> 1402 1403 <label for="PdfLanguageId">@Translate("Language")</label> 1404 <select id="PdfLanguageId" name="PdfLanguageId" class="u-full-width"> 1405 @foreach (var lang in Services.Languages.GetLanguages().OrderBy(l => l.Name)) 1406 { 1407 var selected = lang.IsDefault ? "selected" : ""; 1408 <option value="@lang.LanguageId" @selected>@lang.Name</option> 1409 } 1410 </select> 1411 <label for="PdfPageId">@Translate("Generate PDF")</label> 1412 <select id="PdfPageId" name="PdfPageId" class="u-full-width"> 1413 <option value="" selected>@Translate("Select type")</option> 1414 @foreach (Dynamicweb.Content.Page page in ServiceLocator.Current.GetPageService().GetPagesByParentID(pdfFolderId)) 1415 { 1416 <option value="@page.ID">@page.MenuText</option> 1417 } 1418 </select> 1419 1420 <input type="submit" value="@Translate("Generate PDF")" class="btn btn--full btn--primary u-no-margin dw-mod" title="@Translate("Generate PDF")" /> 1421 </form> 1422 </div> 1423 </div> 1424 } 1425 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1426 @using Dynamicweb.Core 1427 @using System 1428 @using System.Web 1429 @using System.Collections.Generic 1430 @using Dynamicweb.Rapido.Blocks 1431 1432 @functions { 1433 BlocksPage productDescriptionPage = BlocksPage.GetBlockPage("Product"); 1434 } 1435 1436 @{ 1437 string fullDesctiptionLayout = !String.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductPage").GetString("FullDescriptionLayout")) ? Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue : "Section"; 1438 fullDesctiptionLayout = fullDesctiptionLayout == "Ribbon" ? "Section" : fullDesctiptionLayout; 1439 1440 if (!string.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")) && fullDesctiptionLayout != "hide") 1441 { 1442 Block detailsDescription = new Block() 1443 { 1444 Name = fullDesctiptionLayout != "MainInformation" ? Translate("Description") : "", 1445 Id = "FullDescription", 1446 SortId = 10, 1447 Template = RenderProductDescription(fullDesctiptionLayout), 1448 Design = new Design 1449 { 1450 Size = "12", 1451 RenderType = RenderType.Column, 1452 HidePadding = true 1453 } 1454 }; 1455 productDescriptionPage.Add(fullDesctiptionLayout, detailsDescription); 1456 } 1457 } 1458 1459 @helper RenderProductDescription(string layout) 1460 { 1461 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1462 ribbonClasses = layout == "Tabs" ? "u-no-padding" : ribbonClasses; 1463 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("FullDescriptionLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 1464 1465 <div class="product__section @ribbonClasses dw-mod"> 1466 <div class="product__description center-container @ribbonSubClasses dw-mod"> 1467 @if (layout == "Section") { 1468 <h2>@Translate("Description")</h2> 1469 } 1470 1471 @GetString("Ecom:Product.LongDescription") 1472 </div> 1473 </div> 1474 } 1475 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1476 @using Dynamicweb.Core 1477 @using System 1478 @using System.Web 1479 @using System.Globalization; 1480 @using System.Collections.Generic 1481 @using Dynamicweb.Rapido.Blocks 1482 1483 @functions { 1484 BlocksPage productFieldsPage = BlocksPage.GetBlockPage("Product"); 1485 1486 static string ConvertBytes(long bytes) 1487 { 1488 double size = bytes / 1024; //KB 1489 if (size > 1024) 1490 { 1491 size = (bytes / 1024f) / 1024f; //MB 1492 return string.Format("{0:n1} MB", size); 1493 } 1494 else 1495 { 1496 return string.Format("{0:n0} KB", size); 1497 } 1498 } 1499 1500 static bool isImage(string path) 1501 { 1502 return new List<string> { ".jpg", ".jpeg", ".gif", ".png", ".svg" }.Contains(Path.GetExtension(path).ToLower()); 1503 } 1504 1505 string getIconForFile(string fileName) 1506 { 1507 string ext = Path.GetExtension(fileName); 1508 string icon = ""; 1509 switch (ext.ToLower()) 1510 { 1511 case ".xls": 1512 case ".xlsx": 1513 icon = "fa-file-excel"; 1514 break; 1515 case ".ppt": 1516 case ".pptx": 1517 icon = "fa-file-powerpoint"; 1518 break; 1519 case ".doc": 1520 case ".docx": 1521 icon = "fa-file-word"; 1522 break; 1523 case ".jpg": 1524 case ".jpeg": 1525 case ".png": 1526 case ".gif": 1527 case ".pdf": 1528 return "<img class='product__document-img' alt='" + fileName + "' src='/Admin/Public/GetImage.ashx?crop=5&height=70&width=120&Compression=75&DoNotUpscale=true&image=" + fileName + "' />"; 1529 default: 1530 icon = "fa-file"; 1531 break; 1532 } 1533 return "<i class='product__document-icon far " + icon + "'></i> "; 1534 } 1535 } 1536 1537 @*downloadDocuments variable, declared in Product.cshtml - this variable also will be used in ProductAssets.cshtml*@ 1538 1539 @{ 1540 foreach (LoopItem customField in GetLoop("CustomFieldValues")) 1541 { 1542 if (!string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(customField.GetString("Product.CustomField.Value.Clean")) && customField.GetString("Product.CustomField.Name") != "Custom sticker") 1543 { 1544 customFieldsWithValue.Add(customField); 1545 1546 if (!string.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1547 { 1548 downloadDocuments.Add(customField); 1549 } 1550 } 1551 } 1552 1553 foreach (LoopItem customField in GetLoop("ProductCategories")) 1554 { 1555 foreach (LoopItem field in customField.GetLoop("ProductCategoryFields")) 1556 { 1557 if (!string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Value"))) 1558 { 1559 if (field.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1560 { 1561 downloadDocuments.Add(field); 1562 } 1563 } 1564 } 1565 } 1566 1567 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 1568 string detailFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsLayout").SelectedValue : "Section"; 1569 detailFieldsLayout = detailFieldsLayout == "Ribbon" || string.IsNullOrEmpty(detailFieldsLayout) ? "Section" : detailFieldsLayout; 1570 string categoryFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsLayout").SelectedValue : "Section"; 1571 categoryFieldsLayout = categoryFieldsLayout == "Ribbon" || string.IsNullOrEmpty(categoryFieldsLayout) ? "Section" : categoryFieldsLayout; 1572 string downloadsFieldsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsLayout").SelectedValue : "Section"; 1573 downloadsFieldsLayout = downloadsFieldsLayout == "Ribbon" || string.IsNullOrEmpty(downloadsFieldsLayout) ? "Section" : downloadsFieldsLayout; 1574 1575 string detailFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DetailFieldsView").SelectedValue : "grid"; 1576 string categoryFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("CategoryFieldsView").SelectedValue : "grid"; 1577 string downloadsFieldsView = Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsFieldsView") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("DownloadsFieldsView").SelectedValue : "grid"; 1578 1579 if (customFieldsWithValue.Count + downloadDocuments.Count > 0 && detailFieldsLayout != "hide") 1580 { 1581 Block detailsCustom = new Block() 1582 { 1583 Name = detailFieldsLayout != "MainInformation" ? Translate("Details") : "", 1584 Id = "CustomFields", 1585 SortId = 30, 1586 Template = RenderProductSection(detailFieldsLayout, detailFieldsView, Translate("Information"), RenderCustomFields(GetLoop("CustomFieldValues"), detailFieldsView)), 1587 Design = new Design 1588 { 1589 Size = "12", 1590 RenderType = RenderType.Column, 1591 HidePadding = true 1592 } 1593 }; 1594 1595 productFieldsPage.Add(detailFieldsLayout, detailsCustom); 1596 } 1597 1598 if (categoryFieldsLayout != "hide") 1599 { 1600 foreach (LoopItem categoryGroup in GetLoop("ProductCategories")) 1601 { 1602 bool hasFields = categoryGroup.GetLoop("ProductCategoryFields").FirstOrDefault(cf => !string.IsNullOrEmpty(cf.GetString("Ecom:Product.CategoryField.Value"))) != null; 1603 1604 if (collectAllDownloads) { 1605 int downloadableCount = 0; 1606 foreach (LoopItem field in categoryGroup.GetLoop("ProductCategoryFields")) 1607 { 1608 if (field.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1609 { 1610 downloadableCount++; 1611 } 1612 } 1613 1614 if (downloadableCount == categoryGroup.GetLoop("ProductCategoryFields").Count) { 1615 hasFields = false; 1616 } 1617 } 1618 1619 if (hasFields) 1620 { 1621 Block detailsCategoryFields = new Block() 1622 { 1623 Name = categoryFieldsLayout != "MainInformation" ? categoryGroup.GetString("Ecom:Product.Category.Name") : "", 1624 Id = ToPascalCase(categoryGroup.GetString("Ecom:Product.Category.Name")), 1625 SortId = 40, 1626 Template = RenderProductSection(categoryFieldsLayout, categoryFieldsView, categoryGroup.GetString("Ecom:Product.Category.Name"), RenderProductCategoryFields(categoryGroup.GetLoop("ProductCategoryFields"), categoryFieldsView)), 1627 Design = new Design 1628 { 1629 Size = "12", 1630 RenderType = RenderType.Column, 1631 HidePadding = true 1632 } 1633 }; 1634 1635 productFieldsPage.Add(categoryFieldsLayout, detailsCategoryFields); 1636 } 1637 } 1638 } 1639 1640 if (downloadDocuments.Count > 0 && downloadsFieldsLayout != "hide" && collectAllDownloads == true) 1641 { 1642 Block detailsDownloads = new Block() 1643 { 1644 Name = downloadsFieldsLayout != "MainInformation" ? Translate("Downloads") : "", 1645 Id = "StandardDownloads", 1646 SortId = 50, 1647 Template = RenderProductSection(downloadsFieldsLayout, downloadsFieldsView, Translate("Downloads"), RenderProductDownloadsFields(downloadDocuments, downloadsFieldsView)), 1648 Design = new Design 1649 { 1650 Size = "12", 1651 RenderType = RenderType.Column, 1652 HidePadding = true 1653 } 1654 }; 1655 1656 productFieldsPage.Add(downloadsFieldsLayout, detailsDownloads); 1657 } 1658 } 1659 1660 @helper RenderCustomFields(List<LoopItem> fieldsLoop, string viewType) 1661 { 1662 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 1663 1664 foreach (LoopItem customField in fieldsLoop) 1665 { 1666 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 1667 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 1668 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 1669 1670 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 1671 { 1672 fieldValue = customField.GetString("Product.CustomField.Label"); 1673 } 1674 1675 if (!string.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) && !string.IsNullOrEmpty(fieldValue) && customField.GetString("Product.CustomField.Name") != "Custom sticker") 1676 { 1677 if (string.IsNullOrEmpty(customField.GetString("Document.FullPath")) && collectAllDownloads == false) 1678 { 1679 @RenderFieldItem(customField.GetString("Product.CustomField.Name"), fieldValue, viewType); 1680 } 1681 else if (collectAllDownloads == false) 1682 { 1683 @RenderFieldItem(customField.GetString("Product.CustomField.Name"), fieldValue, viewType, "download"); 1684 } 1685 } 1686 } 1687 } 1688 1689 @helper RenderProductSection(string layout, string viewType, string name, RazorEngine.Templating.TemplateWriter writer) { 1690 string ribbonClasses = layout == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1691 ribbonClasses = layout == "Tabs" ? "u-no-padding" : ribbonClasses; 1692 string ribbonSubClasses = layout == "Ribbon" ? "center-container--ribbon" : ""; 1693 1694 <div class="product__section @ribbonClasses dw-mod"> 1695 <div class="center-container @ribbonSubClasses dw-mod"> 1696 @if (layout == "Section") 1697 { 1698 <h2>@name</h2> 1699 } 1700 1701 @if (viewType != "table") 1702 { 1703 <div class="grid grid--bleed u-margin-bottom--lg"> 1704 @writer 1705 </div> 1706 } 1707 else 1708 { 1709 string tableWidth = layout != "MainInformation" ? "grid__col-md-6" : "grid__col-md-12"; 1710 1711 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1712 <div class="@tableWidth grid__col-sm-12 grid__col-xs-12"> 1713 <table class="table--no-top-border"> 1714 @writer 1715 </table> 1716 </div> 1717 </div> 1718 } 1719 </div> 1720 </div> 1721 } 1722 1723 @helper RenderProductCategoryFields(List<LoopItem> fieldsLoop, string viewType) { 1724 bool collectAllDownloads = Pageview.AreaSettings.GetItem("ProductPage").GetString("CollectAllDownloads") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("CollectAllDownloads") : true; 1725 1726 foreach (LoopItem categoryField in fieldsLoop) 1727 { 1728 string fieldValue = categoryField.GetString("Ecom:Product.CategoryField.Value"); 1729 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 1730 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 1731 1732 if (!string.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Label")) && !string.IsNullOrEmpty(fieldValue)) 1733 { 1734 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") != "9" || collectAllDownloads == false) 1735 { 1736 if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "15") 1737 { 1738 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), categoryField.GetString("Ecom:Product.CategoryField.OptionLabel"), viewType); 1739 } 1740 else if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "8") 1741 { 1742 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "link"); 1743 } 1744 else if (categoryField.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1745 { 1746 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType, "download"); 1747 } 1748 else 1749 { 1750 @RenderFieldItem(categoryField.GetString("Ecom:Product.CategoryField.Label"), fieldValue, viewType); 1751 } 1752 } 1753 } 1754 } 1755 } 1756 1757 @helper RenderProductDownloadsFields(List<LoopItem> fieldsLoop, string viewType) { 1758 foreach (LoopItem document in fieldsLoop) 1759 { 1760 string fieldValue; 1761 if (!string.IsNullOrEmpty(document.GetString("Document.FullPath"))) 1762 { 1763 fieldValue = document.GetString("Product.CustomField.Value.Clean"); 1764 @RenderFieldItem(fieldValue, document.GetString("Document.FullPath"), viewType, "download") 1765 } 1766 1767 if (document.GetString("Ecom:Product.CategoryField.TypeID") == "9") 1768 { 1769 fieldValue = document.GetString("Ecom:Product.CategoryField.Value"); 1770 @RenderFieldItem(fieldValue, fieldValue, viewType, "download") 1771 } 1772 } 1773 } 1774 1775 @helper RenderFieldItem(string name, string value, string viewType, string fieldType = "clean") 1776 { 1777 if (viewType != "table") 1778 { 1779 string fieldColumns = viewType == "list" ? "12" : "4"; 1780 <div class="grid__col-md-@fieldColumns grid__col-sm-12 u-margin-bottom"> 1781 <div class="u-bold"> 1782 @name 1783 </div> 1784 <div> 1785 @RenderFieldItemContent(name, value, fieldType) 1786 </div> 1787 </div> 1788 } 1789 else 1790 { 1791 <tr> 1792 <th>@name</th> 1793 <td class="@fieldType"> 1794 @RenderFieldItemContent(name, value, fieldType) 1795 </td> 1796 </tr> 1797 } 1798 } 1799 1800 @helper RenderFieldItemContent(string name, string value, string fieldType = "clean") 1801 { 1802 if (fieldType == "link") 1803 { 1804 <a target="_blank" rel="noopener" href="@value"> 1805 @if (isImage(value)) 1806 { 1807 @getIconForFile(value) 1808 } 1809 else 1810 { 1811 @value 1812 } 1813 </a> 1814 } 1815 else if (fieldType == "download") 1816 { 1817 FileInfo info = new FileInfo(Dynamicweb.Core.SystemInformation.MapPath(value)); 1818 1819 if (info.Exists) 1820 { 1821 <div class="grid grid--no-wrap"> 1822 <a href="@value" download title="@Translate("Download")" class="product__document u-min-w120px u-ta-center dw-mod">@getIconForFile(value)</a> 1823 <div class="product__document-info dw-mod"> 1824 <a href="@value" download title="@Translate("Download")" class="product__document dw-mod">@Path.GetFileName(value)</a> 1825 <small class="u-block u-margin-top">@ConvertBytes(info.Length)</small> 1826 </div> 1827 </div> 1828 } 1829 } 1830 else 1831 { 1832 @value 1833 } 1834 } 1835 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1836 @using Dynamicweb.Core 1837 @using System 1838 @using System.Web 1839 @using System.Collections.Generic 1840 @using Dynamicweb.Rapido.Blocks 1841 1842 @functions{ 1843 BlocksPage productVideoPage = BlocksPage.GetBlockPage("Product"); 1844 } 1845 1846 @{ 1847 string videosLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue : "Section"; 1848 videosLayout = videosLayout == "Ribbon" || string.IsNullOrEmpty(videosLayout) ? "Section" : videosLayout; 1849 1850 int videosCount = 0; 1851 1852 foreach (LoopItem detailField in GetLoop("Details")) 1853 { 1854 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("youtube.com/embed") != -1) 1855 { 1856 videosCount++; 1857 } 1858 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("vimeo.com") != -1) 1859 { 1860 videosCount++; 1861 } 1862 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("video") != -1 ) 1863 { 1864 videosCount++; 1865 } 1866 } 1867 1868 if (videosCount > 0 && videosLayout != "hide") 1869 { 1870 Block detailsVideos = new Block() 1871 { 1872 Name = videosLayout != "MainInformation" ? Translate("Videos") : "", 1873 Id = "Videos", 1874 SortId = 60, 1875 Template = ProductVideos(videosCount, videosLayout), 1876 Design = new Design 1877 { 1878 Size = "12", 1879 RenderType = RenderType.Column 1880 } 1881 }; 1882 productVideoPage.Add(videosLayout, detailsVideos); 1883 } 1884 } 1885 1886 @* 1887 <div style="display:none;" t=t>..T.. @videosCount 1888 @foreach (LoopItem detailsField in GetLoop("Details")){ 1889 detailsField.TemplateTags () 1890 } 1891 @foreach (LoopItem i in GetLoop("Ecom:Product.AlternativeImages")) { 1892 i.TemplateTags () 1893 } 1894 TemplateTags () 1895 </div> 1896 *@ 1897 1898 1899 1900 1901 @helper ProductVideos(int videosCount, string layout) { 1902 string videoColumn = "12"; 1903 videoColumn = videosCount == 2 ? "6" : videoColumn; 1904 videoColumn = videosCount > 2 ? "4" : videoColumn; 1905 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 1906 ribbonClasses = layout == "Tabs" ? "u-no-padding" : ribbonClasses; 1907 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VideosLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 1908 1909 <div class="product__section @ribbonClasses dw-mod"> 1910 <div class="center-container @ribbonSubClasses dw-mod"> 1911 @if (layout == "Section") { 1912 <h2>@Translate("Videos")</h2> 1913 } 1914 1915 <div class="grid grid--external-bleed-x u-margin-bottom--lg"> 1916 @foreach (LoopItem detailField in GetLoop("Details")) 1917 { 1918 if (detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("youtube.com/embed") != -1 || detailField.GetString("Ecom:Product:Detail.Text").IndexOf("iframe") != -1 && detailField.GetString("Ecom:Product:Detail.Text").IndexOf("vimeo.com") != -1) 1919 { 1920 <div class="grid__col-md-@videoColumn grid__col-lg-@videoColumn"> 1921 <div class="video-wrapper"> 1922 @detailField.GetString("Ecom:Product:Detail.Text").Replace("560", "auto").Replace("315", "auto") 1923 </div> 1924 </div> 1925 } 1926 } 1927 </div> 1928 </div> 1929 </div> 1930 } 1931 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 1932 @using Dynamicweb.Core 1933 @using System 1934 @using System.Web 1935 @using System.Collections.Generic 1936 @using Dynamicweb.Rapido.Blocks 1937 1938 @functions{ 1939 BlocksPage productRelatedPage = BlocksPage.GetBlockPage("Product"); 1940 } 1941 1942 @{ 1943 string relatedProductsLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue : "Section"; 1944 relatedProductsLayout = relatedProductsLayout == "Ribbon" || string.IsNullOrEmpty(relatedProductsLayout) ? "Section" : relatedProductsLayout; 1945 bool relatedOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 1946 bool relatedShowStock = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowStockAndShipping"); 1947 bool showAddToDownloadButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToDownloadButton"); 1948 bool relatedShowPrice = !Pageview.AreaSettings.GetItem("ProductList").GetBoolean("HidePrice"); 1949 bool relatedShowFavoriteButton = !Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("HideFavoriteButton") && Pageview.User != null; 1950 bool relatedPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 1951 bool relatedShowCartButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowAddToCartButton"); 1952 bool relatedShowViewButton = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowViewButton"); 1953 string relatedCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 1954 string relatedMoreText = !string.IsNullOrEmpty(Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetString("ViewMoreText")) ? Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetString("ViewMoreText") : "View"; 1955 bool relatedShowNumber = Pageview.AreaSettings.GetItem("ProductList").GetItem("GridView").GetBoolean("ShowProductNumber"); 1956 1957 int relatedProductsPageSize = 4; 1958 int relatedProductsColumnWidth = 3; 1959 1960 if (Pageview.Device.ToString() == "Mobile") 1961 { 1962 relatedProductsPageSize = 1; 1963 relatedProductsColumnWidth = 12; 1964 } 1965 1966 if (Pageview.Device.ToString() == "Tablet") 1967 { 1968 relatedProductsPageSize = 3; 1969 relatedProductsColumnWidth = 4; 1970 } 1971 1972 if (relatedProductsLayout != "hide") 1973 { 1974 foreach (LoopItem relatedGroup in GetLoop("ProductRelatedGroups")) 1975 { 1976 string relatedGroupId = ToPascalCase(relatedGroup.GetString("Ecom:Product:RelatedGroup.Name")); 1977 1978 relatedGroupId = "RelateredeVarer"; 1979 1980 1981 1982 string baseFeedPageUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + relatedProductsPageSize + "&ProdID=" + GetString("Ecom:Product.ID") + "&feed=true"; 1983 string relatedFeed = baseFeedPageUrl + "&" + relatedGroupId + "=" + GetString("Ecom:Product.ID") + "&GroupName=" + relatedGroupId; 1984 string relatedGroupName = relatedProductsLayout != "maininformation" ? relatedGroup.GetString("Ecom:Product:RelatedGroup.Name") : ""; 1985 1986 Block detailsRelated = new Block() 1987 { 1988 Name = relatedGroupName, 1989 Id = relatedGroupId, 1990 SortId = 70, 1991 Template = RenderRelatedProducts(relatedGroupName, relatedGroupId, relatedFeed, relatedProductsLayout), 1992 Design = new Design 1993 { 1994 Size = "12", 1995 RenderType = RenderType.Column, 1996 HidePadding = true 1997 } 1998 }; 1999 2000 productRelatedPage.Add(relatedProductsLayout, detailsRelated); 2001 } 2002 } 2003 } 2004 2005 @helper RenderRelatedProducts(string name, string groupId, string relatedFeedUrl, string layout) 2006 { 2007 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 2008 ribbonClasses = layout == "Tabs" ? "u-no-padding" : ribbonClasses; 2009 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("RelatedProductsLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 2010 2011 <div class="product__section @ribbonClasses dw-mod"> 2012 <div class="center-container @ribbonSubClasses dw-mod"> 2013 @if (layout == "Section") { 2014 <h2>@name</h2> 2015 } 2016 2017 <div class="js-handlebars-root" id="ProductList_@groupId" data-template="ProductContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedFeedUrl" data-preloader="minimal"></div> 2018 </div> 2019 </div> 2020 } 2021 2022 @* Script templates for related products *@ 2023 <script id="ProductPreRenderContainer" type="text/x-template"> 2024 <div class="u-h600px u-full-width"> 2025 <div class="grid"> 2026 <div class="grid__col-12"> 2027 <div class="pre-render-element pre-render-element--md"></div> 2028 </div> 2029 </div> 2030 </div> 2031 </script> 2032 2033 <script id="ProductContainer" type="text/x-template"> 2034 {{#.}} 2035 <div class="u-min-h400px u-full-width"> 2036 <div class="grid"> 2037 <div class="grid__col-45px grid__col--bleed-x"> 2038 <div class="grid__cell grid__cell--align-middle-left"> 2039 <button class="btn btn--condensed btn--clean {{prevdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{prevPage}}')" {{prevdisabled}}><i class="fas fa-chevron-left fa-2x"></i></button> 2040 </div> 2041 </div> 2042 <div class="grid__col-auto grid__col--bleed-x"> 2043 <div id="ProductsContainer" data-template="ProductGridItemContainer" class="grid product-list dw-mod" data-save-cookie="true"> 2044 {{#ProductsContainer}} 2045 <div id="Product{{productId}}" class="grid__col-@relatedProductsColumnWidth product-list__grid-item dw-mod"> 2046 {{#Product}} 2047 @if (useGoogleTagManager) 2048 { 2049 <text>{{{googleEnchantImpression 'Related products' currency googleImpression}}}</text> 2050 } 2051 <div class="grid__cell product-list__grid-item__image dw-mod {{noImage}}"> 2052 <a href="{{link}}" onclick="Scroll.SavePosition(event)" class="u-block u-position-relative"> 2053 <img class="grid__cell-img grid__cell-img--centered b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=300&amp;height=300&amp;crop=5&amp;Compression=75&amp;image={{image}}" alt="{{name}}" /> 2054 {{#StickersContainers}} 2055 {{>StickersContainer}} 2056 {{/StickersContainers}} 2057 </a> 2058 @if (relatedShowFavoriteButton) 2059 { 2060 <div class="favorites favorites--for-grid-view u-pull--right {{hasVariants}} dw-mod" {{hasVariants}}> 2061 {{#Favorite}} 2062 {{>FavoriteTemplate}} 2063 {{/Favorite}} 2064 </div> 2065 } 2066 </div> 2067 2068 <div class="grid__cell product-list__grid-item__price-info {{shortGridInfo}} dw-mod"> 2069 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-condensed-text">{{name}}</h6></a> 2070 2071 @if (relatedShowNumber) 2072 { 2073 <div class="item-number dw-mod">{{number}}</div> 2074 } 2075 2076 @if (relatedShowPrice && !relatedOnlyPreview) 2077 { 2078 if (relatedPointShopOnly) 2079 { 2080 <text> 2081 {{#if havePointPrice}} 2082 <div>{{points}} @Translate("points")</div> 2083 {{else}} 2084 @Translate("Not available") 2085 {{/if}} 2086 </text> 2087 } 2088 else 2089 { 2090 <div class="price price--product-list dw-mod">{{price}}</div> 2091 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 2092 } 2093 } 2094 </div> 2095 2096 <div class="product-list__grid-item__footer dw-mod"> 2097 @if (relatedShowCartButton && !relatedOnlyPreview) 2098 { 2099 <div class="u-ta-center u-inline-block"> 2100 <div class="buttons-collection {{hideBuyOptions}}"> 2101 @if (relatedPointShopOnly) 2102 { 2103 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed u-no-margin dw-mod js-cart-btn {{disabledBuyButton}} {{#unless canBePurchasedWithPoints}}js-stay-disabled{{/unless}}" name="CartCmd" value="addWithPoints" 2104 onclick="Cart.AddToCart(event, { 2105 id: {{productId}}', 2106 variantId: '{{variantid}}', 2107 unitId: '{{unitId}}', 2108 quantity: 1, 2109 buyForPoints: true, 2110 productInfo: {{productInfo}} 2111 }); {{facebookPixelAction}}" {{disabledBuyButton}}> 2112 <i class="@relatedCartIcon"></i><span class="u-hidden-xs u-hidden-xxs"> @Translate("Buy with points")</span> 2113 </button> 2114 } 2115 else 2116 { 2117 <button type="button" id="CartButton_{{id}}" class="js-cart-btn btn btn--primary btn--condensed u-no-margin u-pull--right dw-mod {{disabledBuyButton}}" name="submit" 2118 onclick="Cart.AddToCart(event, { 2119 id: '{{productId}}', 2120 variantId: '{{variantid}}', 2121 unitId: '{{unitId}}', 2122 quantity: document.getElementById('Quantity_{{id}}').value, 2123 productInfo: {{productInfo}} 2124 }); {{facebookPixelAction}}" {{disabledBuyButton}}> 2125 <i class="@relatedCartIcon"></i><span class="u-hidden-xs u-hidden-xxs" style="font-size:10px;"> @Translate("Add to cart")</span> 2126 </button> 2127 <input type="number" class="u-w60px u-pull--right" id="Quantity_{{id}}" name="Quantity{{id}}" value="1" min="1"> 2128 } 2129 </div> 2130 </div> 2131 2132 if (relatedShowViewButton) 2133 { 2134 <div class="u-ta-center {{hideViewMore}}"> 2135 <a href="{{link}}" id="CartButton_{{id}}" class="btn btn--secondary btn--full u-no-margin dw-mod" onclick="Scroll.SavePosition(event); {{googleImpressionClick}}" title="@Translate(relatedMoreText)">@Translate(relatedMoreText)</a> 2136 </div> 2137 } 2138 2139 } 2140 else if (relatedShowViewButton) 2141 { 2142 <div class="u-ta-center"> 2143 <a href="{{link}}" id="CartButton_{{id}}" class="btn btn--secondary btn--full u-no-margin dw-mod" onclick="Scroll.SavePosition(event); {{googleImpressionClick}}" title="@Translate(relatedMoreText)">@Translate(relatedMoreText)</a> 2144 </div> 2145 } 2146 2147 @if (!relatedOnlyPreview && relatedShowStock) 2148 { 2149 <div class="u-margin-top"> 2150 <div><span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> {{stockText}}</div> 2151 <div> 2152 {{#if deliveryText}} 2153 {{deliveryText}} 2154 {{else}} 2155 - 2156 {{/if}} 2157 </div> 2158 </div> 2159 } 2160 2161 @if (showAddToDownloadButton && Pageview.User != null) 2162 { 2163 <button type="button" class="btn btn--primary u-no-margin u-margin-top btn--condensed dw-mod js-add-to-downloads" title="@Translate("Add")" data-product-id="{{productId}}"> 2164 <i class="fas fa-plus js-button-icon"></i> 2165 <span class="js-button-text">@Translate("Add")</span> 2166 </button> 2167 } 2168 </div> 2169 {{/Product}} 2170 </div> 2171 {{/ProductsContainer}} 2172 </div> 2173 </div> 2174 <div class="grid__col-45px grid__col--bleed-x"> 2175 <div class="grid__cell grid__cell--align-middle-right"> 2176 <button class="btn btn--condensed btn--clean {{nextdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{nextPage}}')" {{nextdisabled}}><i class="fas fa-chevron-right fa-2x"></i></button> 2177 </div> 2178 </div> 2179 </div> 2180 </div> 2181 {{/.}} 2182 </script> 2183 2184 @* Favorites templates *@ 2185 2186 <script id="FavoriteTemplate" type="text/x-template"> 2187 <div class="favorites-list u-ta-left"> 2188 <label for="FavoriteTrigger_{{id}}" class="u-no-margin"><i class="{{favoriteIcon}} fa-1_5x"></i></label> 2189 <input type="checkbox" id="FavoriteTrigger_{{id}}" class="dropdown-trigger" /> 2190 <div class="dropdown dropdown--absolute-position"> 2191 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 2192 <ul class="list list--clean dw-mod"> 2193 {{#FavoriteLists}} 2194 {{>FavoriteListItem}} 2195 {{/FavoriteLists}} 2196 </ul> 2197 </div> 2198 <label class="dropdown-trigger-off" for="FavoriteTrigger_{{id}}"></label> 2199 </div> 2200 </div> 2201 </script> 2202 2203 <script id="StickersContainer" type="text/x-template"> 2204 <div class="stickers-container stickers-container--{{position}} dw-mod"> 2205 {{#Stickers}} 2206 {{>Sticker}} 2207 {{/Stickers}} 2208 </div> 2209 </script> 2210 2211 <script id="Sticker" type="text/x-template"> 2212 <div class="stickers-container__tag {{className}} dw-mod">{{text}}</div> 2213 </script> 2214 2215 <script id="FavoriteListItem" type="text/x-template"> 2216 <li> 2217 <a href="{{link}}" class="list__link u-no-underline dw-mod" onclick="{{facebookPixelAction}}"><i class="{{favoriteIcon}}"></i> {{name}}</a> 2218 </li> 2219 </script> 2220 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2221 @using Dynamicweb.Core 2222 @using System 2223 @using System.Web 2224 @using System.Collections.Generic 2225 @using Dynamicweb.Rapido.Blocks 2226 2227 @functions { 2228 BlocksPage productVariantsPage = BlocksPage.GetBlockPage("Product"); 2229 } 2230 2231 @{ 2232 bool renderVariantsAsProducts = GetInteger("Ecom:Product.VariantCount") > 1 && Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantsAsProductList"); 2233 bool variantsOnlyPreview = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("OnlyPreviewForAnonymous") && Pageview.User == null; 2234 bool showProductNumberForVariants = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideProductNumbers"); 2235 bool showImageForEachVariant = !Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("HideImageForEachVariant"); 2236 bool variantsPointShopOnly = Pageview.AreaSettings.GetItem("Ecommerce").GetBoolean("PointShopOnly"); 2237 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") ?? "30"; 2238 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 2239 string variantsCartIcon = Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon") != null ? Pageview.AreaSettings.GetItem("Layout").GetItem("Icons").GetList("CartIcon").SelectedValue : "fas fa-shopping-cart"; 2240 string variantsListLayout = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout") != null ? Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue : "Section"; 2241 variantsListLayout = variantsListLayout == "Ribbon" ? "Section" : variantsListLayout; 2242 2243 if (renderVariantsAsProducts && variantsListLayout != "hide") 2244 { 2245 Block detailsVariantsList = new Block() 2246 { 2247 Name = variantsListLayout != "MainInformation" ? Translate("Variants list") : "", 2248 Id = "VariantsList", 2249 SortId = 20, 2250 Template = RenderVariantsProductList(variantsListLayout), 2251 Design = new Design 2252 { 2253 Size = "12", 2254 RenderType = RenderType.Column, 2255 HidePadding = true 2256 } 2257 }; 2258 productVariantsPage.Add(variantsListLayout, detailsVariantsList); 2259 } 2260 } 2261 2262 @helper RenderVariantsProductList(string layout) 2263 { 2264 string variantsListPageSize = HttpContext.Current.Request.QueryString.Get("PageSize") ?? "30"; 2265 string variantsFeedUrl = "/Default.aspx?ID=" + GetPageIdByNavigationTag("ProductsPage") + "&PageSize=" + variantsListPageSize + "&MainProductID=" + GetString("Ecom:Product.ID") + "&OnlyShowVariants=true&feed=true"; 2266 string ribbonClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "product__section--ribbon paragraph-container paragraph-container--full-width" : ""; 2267 ribbonClasses = layout == "Tabs" ? "u-no-padding" : ribbonClasses; 2268 string ribbonSubClasses = Pageview.AreaSettings.GetItem("ProductPage").GetList("VariantsListLayout").SelectedValue == "Ribbon" ? "center-container--ribbon" : ""; 2269 2270 <div class="product__section @ribbonClasses dw-mod"> 2271 <div class="center-container @ribbonSubClasses dw-mod"> 2272 @if (layout == "Section") { 2273 <h2>@Translate("Variants")</h2> 2274 } 2275 2276 <div class="js-handlebars-root" id="VariantsListRoot" data-template="VariantProductsContainer" data-json-feed="@variantsFeedUrl" data-preloader="minimal"></div> 2277 </div> 2278 </div> 2279 } 2280 2281 2282 @* Script templates for variant products *@ 2283 2284 <script id="VariantProductsContainer" type="text/x-template"> 2285 {{#.}} 2286 <div class=""> 2287 <table id="VariantsProductsContainer" class="table u-position-relative dw-mod"> 2288 <thead> 2289 <tr> 2290 @if (showImageForEachVariant) 2291 { 2292 <td width="75">&nbsp;</td> 2293 } 2294 <td>@Translate("Product")</td> 2295 {{#AvailableCustomFields}} 2296 {{>TableFieldNameTemplate}} 2297 {{/AvailableCustomFields}} 2298 @if (Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantGroupsInTable")) { 2299 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 2300 { 2301 <td>@variantgroup.GetString("Ecom:VariantGroup.Name")</td> 2302 } 2303 } 2304 <td width="360">&nbsp;</td> 2305 </tr> 2306 </thead> 2307 2308 <tbody id="VariantProductListContainer" data-template="VariantProductItemContainer" data-save-cookie="true"> 2309 {{#ProductsContainer}} 2310 {{>VariantProductItemContainer}} 2311 {{/ProductsContainer}} 2312 </tbody> 2313 </table> 2314 </div> 2315 2316 <div class="grid"> 2317 <div class="grid__col-12 grid__col--bleed-y"> 2318 <button type="button" id="LoadMoreButton" class="btn btn--primary btn--full {{nextdisabled}} dw-mod" data-current="{{currentPage}}" data-page-size="{{pageSize}}" data-total="{{totalPages}}" data-container="VariantProductListContainer" data-feed-url="@variantsFeedUrl{{loadMoreFeedParams}}" onclick="LoadMore.Next(this)" {{nextdisabled}}>@Translate("Load") @Translate("more")</button> 2319 </div> 2320 </div> 2321 {{/.}} 2322 </script> 2323 2324 <script id="VariantProductItemContainer" type="text/x-template"> 2325 {{#.}} 2326 <tr id="VariantProduct{{id}}" data-template="VariantProductItem" data-preloader="overlay" style="z-index: {{zIndex}}"> 2327 {{#Product}} 2328 {{>VariantProductItem}} 2329 {{/Product}} 2330 </tr> 2331 {{/.}} 2332 </script> 2333 2334 <script id="VariantProductItem" type="text/x-template"> 2335 {{#.}} 2336 @if (showImageForEachVariant) 2337 { 2338 <td width="75"> 2339 <div class="lightbox u-hidden-xxs"> 2340 <a href="{{link}}" onclick="Scroll.SavePosition(event)"> 2341 <img class="lightbox__image {{noImage}}" src="/Admin/Public/GetImage.ashx?width=220&amp;height=220&amp;crop=5&amp;Compression=75&amp;image={{image}}" alt="{{name}}" /> 2342 <div class="u-margin-right {{noImage}}"> 2343 <img src="/Admin/Public/GetImage.ashx?width=75&amp;height=55&amp;crop=5&FillCanvas=true&amp;Compression=75&amp;image={{image}}" alt="{{name}}" /> 2344 </div> 2345 </a> 2346 </div> 2347 </td> 2348 } 2349 2350 <td class="u-va-middle"> 2351 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-no-margin">{{name}}</h6></a> 2352 <div class="item-number item-number--compressed dw-mod"> 2353 @if (showProductNumberForVariants) 2354 { 2355 <div class="u-margin-bottom">{{number}}</div> 2356 } 2357 @if (!variantsOnlyPreview) 2358 { 2359 <div> 2360 <span class="stock-icon {{stockState}} u-no-margin dw-mod" title="{{stockText}}"></span> {{stockText}} {{deliveryText}} 2361 </div> 2362 } 2363 else 2364 { 2365 <div class="grid__cell-footer stickers-container stickers-container--block dw-mod"> 2366 {{#Stickers}} 2367 {{>MiniSticker}} 2368 {{/Stickers}} 2369 </div> 2370 } 2371 </div> 2372 </td> 2373 {{#CustomFields}} 2374 {{>TableFieldValueTemplate}} 2375 {{/CustomFields}} 2376 @if (Pageview.AreaSettings.GetItem("ProductPage").GetBoolean("RenderVariantGroupsInTable")) 2377 { 2378 <text> 2379 {{#VariantSelectionNames}} 2380 {{>TableFieldNameTemplate}} 2381 {{/VariantSelectionNames}} 2382 </text> 2383 } 2384 <td width="320" class="u-va-middle"> 2385 @if (variantsOnlyPreview) 2386 { 2387 <div class="u-hidden-sm"> 2388 <div class="u-full-width u-ta-right u-padding-right"> 2389 <div class="before-price {{onSale}} before-price--micro dw-mod">{{discount}}</div> 2390 <div class="price price--product-list price--micro dw-mod">{{price}}</div> 2391 </div> 2392 </div> 2393 } 2394 else 2395 { 2396 <div class="grid grid--align-center grid--justify-end"> 2397 <div class="favorites u-margin-right {{hasVariants}} dw-mod" {{hasVariants}}> 2398 {{#Favorite}} 2399 {{>FavoriteTemplate}} 2400 {{/Favorite}} 2401 </div> 2402 <div class="u-margin-right"> 2403 <input type="checkbox" id="UnitOptions_{{id}}" class="dropdown-trigger" /> 2404 <div class="dropdown u-w120px {{hasUnits}} dw-mod"> 2405 <label class="dropdown__header dropdown__btn dw-mod" for="UnitOptions_{{id}}">{{unitName}}</label> 2406 <div id="unitOptions" class="dropdown__content dw-mod"> 2407 {{#unitOptions}} 2408 {{>UnitOption}} 2409 {{/unitOptions}} 2410 </div> 2411 <label class="dropdown-trigger-off" for="UnitOptions_{{id}}"></label> 2412 </div> 2413 <input type="hidden" value="{{unitId}}" name="Unit{{id}}" id="Unit_{{id}}" /> 2414 <input type="hidden" value="{{variantid}}" name="VariantID{{id}}" id="Variant_{{id}}" /> 2415 </div> 2416 <div class="u-margin-right u-hidden-xs u-hidden-xxs"> 2417 @if (variantsPointShopOnly) 2418 { 2419 <text> 2420 {{#if canBePurchasedWithPoints}} 2421 <div class="price price--product-list price--micro dw-mod">{{points}} @Translate("points")</div> 2422 {{else}} 2423 {{#if havePointPrice}} 2424 <small class="help-text u-no-margin u-margin-top">@Translate("Not enough points to buy this")</small> 2425 {{else}} 2426 <small class="help-text u-no-margin u-margin-top">@Translate("Not available")</small> 2427 {{/if}} 2428 {{/if}} 2429 </text> 2430 } 2431 else 2432 { 2433 <div class="before-price before-price--micro {{onSale}} dw-mod">{{discount}}</div> 2434 <div class="price price--condensed price--product-list dw-mod">{{price}}</div> 2435 } 2436 </div> 2437 @if (variantsPointShopOnly) 2438 { 2439 <div> 2440 <button {{#unless canBePurchasedWithPoints}} disabled{{/unless}} type="button" 2441 id="CartButton_{{id}}" 2442 class="btn btn--primary btn--condensed u-no-margin dw-mod js-cart-btn {{#unless canBePurchasedWithPoints}}disabled js-stay-disabled{{/unless}}" 2443 name="CartCmd" 2444 value="addWithPoints" 2445 onclick="Cart.AddToCart(event, { 2446 id: '{{productId}}', 2447 variantId: '{{variantid}}', 2448 unitId: '{{unitId}}', 2449 quantity: 1, 2450 buyForPoints: true, 2451 productInfo: {{productInfo}} 2452 })"> 2453 <i class="@variantsCartIcon"></i> 2454 </button> 2455 </div> 2456 } 2457 else 2458 { 2459 <div> 2460 <input type="number" class="u-w80px u-no-margin u-margin-right" id="Quantity_{{id}}" name="Quantity{{id}}" value="1" min="1"> 2461 </div> 2462 <div> 2463 <button type="button" id="CartButton_{{id}}" class="btn btn--primary btn--condensed u-no-margin dw-mod" name="submit" 2464 onclick="Cart.AddToCart(event, { 2465 id: '{{productId}}', 2466 variantId: '{{variantid}}', 2467 unitId: '{{unitId}}', 2468 quantity: document.getElementById('Quantity_{{id}}').value, 2469 productInfo: {{productInfo}} 2470 });"> 2471 <i class="@variantsCartIcon"></i> 2472 </button> 2473 </div> 2474 } 2475 </div> 2476 } 2477 </td> 2478 {{/.}} 2479 </script> 2480 2481 <script id="TableFieldNameTemplate" type="text/x-template"> 2482 <td class="u-va-middle">{{name}}</td> 2483 </script> 2484 2485 <script id="TableFieldValueTemplate" type="text/x-template"> 2486 <td class="u-va-middle">{{value}}</td> 2487 </script> 2488 2489 <script id="MiniSticker" type="text/x-template"> 2490 <div class="stickers-container__tag stickers-container__tag--micro {{className}} dw-mod">{{text}}</div> 2491 </script> 2492 @if (File.Exists(HttpContext.Current.Server.MapPath("/Files/Templates/Designs/Rapido/eCom/Product/Blocks/Custom__Blocks.cshtml"))) 2493 { 2494 <text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2495 @using Dynamicweb.Core 2496 @using System 2497 @using System.Web 2498 @using System.Collections.Generic 2499 @using Dynamicweb.Rapido.Blocks 2500 2501 @{ 2502 BlocksPage customProductBlocks = BlocksPage.GetBlockPage("Product"); 2503 2504 }</text> 2505 } 2506 2507 2508 <div class="product__info dw-mod u-margin-bottom--lg js-product"> 2509 <div class="grid grid--align-content-start"> 2510 @* The @RenderBlockList base helper is included in Components/GridBuilder.cshtml *@ 2511 @RenderBlockList(productsPage.BlocksRoot.BlocksList) 2512 </div> 2513 </div> 2514 2515 @helper RenderProductTop() { 2516 List<Block> subBlocks = productsPage.GetBlockListById("Top").OrderBy(item => item.SortId).ToList(); 2517 2518 <div class="product__top paragraph-container paragraph-container--full-width dw-mod"> 2519 <div class="center-container u-padding dw-mod"> 2520 <div class="grid"> 2521 @RenderBlockList(subBlocks) 2522 </div> 2523 </div> 2524 </div> 2525 } 2526 2527 @helper RenderProductMiniTabs() { 2528 List<Block> subBlocks = productsPage.GetBlockListById("MiniTabs").OrderBy(item => item.SortId).ToList(); 2529 2530 if (subBlocks.Count > 0) { 2531 <div class="grid__col-12 product__info tabs u-no-padding u-margin-bottom--lg dw-mod"> 2532 @{ 2533 bool firstTab = true; 2534 foreach (Block item in subBlocks) 2535 { 2536 string isChecked = firstTab ? "checked" : ""; 2537 firstTab = false; 2538 2539 <input type="radio" class="tabs__trigger" name="productMiniTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 2540 } 2541 } 2542 2543 <div class="tabs__list dw-mod"> 2544 @foreach (Block item in subBlocks) 2545 { 2546 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 2547 } 2548 </div> 2549 2550 <div class="tabs__blocks dw-mod"> 2551 @foreach (Block item in subBlocks) 2552 { 2553 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 2554 2555 if (item.Design.RenderType != RenderType.Hide) 2556 { 2557 <div class="tabs__block u-border dw-mod" id="Block__@item.Id"> 2558 <block class="product__block paragraph-container product__block--bordered dw-mod"> 2559 <div class="center-container u-padding--lg dw-mod"> 2560 @RenderBlock(item) 2561 </div> 2562 </block> 2563 </div> 2564 } 2565 } 2566 </div> 2567 </div> 2568 } 2569 } 2570 2571 @helper RenderProductTabs() 2572 { 2573 List<Block> subBlocks = productsPage.GetBlockListById("Tabs").OrderBy(item => item.SortId).ToList(); 2574 2575 <div class="grid__col-12 product__info product__info--tabs tabs dw-mod"> 2576 @{ 2577 bool firstTab = true; 2578 foreach (Block item in subBlocks) 2579 { 2580 string isChecked = firstTab ? "checked" : ""; 2581 firstTab = false; 2582 2583 <input type="radio" class="tabs__trigger" name="productTabs" id="@item.Id" onchange="bLazy.revalidate()" @isChecked /> 2584 } 2585 } 2586 2587 <div class="tabs__list dw-mod"> 2588 @foreach (Block item in subBlocks) 2589 { 2590 <label for="@item.Id" class="tabs__label dw-mod">@item.Name</label> 2591 } 2592 </div> 2593 2594 <div class="tabs__blocks dw-mod"> 2595 @foreach (Block item in subBlocks) 2596 { 2597 string hidePadding = item.Design.HidePadding ? "u-no-padding" : ""; 2598 2599 if (item.Design.RenderType != RenderType.Hide) 2600 { 2601 <div class="tabs__block dw-mod" id="Block__@item.Id"> 2602 <section class="product__section paragraph-container paragraph-container--full-width product__section--bordered dw-mod"> 2603 <div class="center-container u-padding--lg dw-mod"> 2604 @RenderBlock(item) 2605 </div> 2606 </section> 2607 </div> 2608 } 2609 } 2610 </div> 2611 </div> 2612 } 2613 @{ 2614 String teaser = ""; 2615 } 2616 @if(string.IsNullOrWhiteSpace(GetString("Meta.Description")) && string.IsNullOrWhiteSpace(GetString("Ecom:Product.MetaDescription"))) { 2617 teaser = GetString("Ecom:Product.ShortDescription"); 2618 teaser = Regex.Replace(teaser, @"<[^>]*>", String.Empty); 2619 if(teaser.Length>160){ 2620 teaser = teaser.Substring(0,165); 2621 teaser = teaser.Substring(0,teaser.LastIndexOf('.')+1); 2622 } 2623 <!--$$SnippetStart(HeaderStart)--> 2624 <meta name="description" content="@teaser"> 2625 <!--$$SnippetEnd(HeaderStart)--> 2626 } 2627 2628 <!--$$SnippetStart(HeaderStart)--> 2629 <meta property="og:description" content="@(teaser)" /> 2630 <meta property="og:image" content="https://@(GetGlobalValue("Global:Request.Host"))/Admin/Public/Getimage.ashx?width=900&height=600&compression=85&crop=0&image=/Files/Images/Ecom/Products/@(GetString("Ecom:Product.Number")).jpg" /> 2631 <!--$$SnippetEnd(HeaderStart)--> 2632 2633 <script type="text/javascript"> 2634 $(document).ready(function(){ 2635 $(".longdesc_expand").click(function(){ 2636 if($(this).hasClass('fn_expand')) { 2637 $(".longdesc_container").removeClass("longdesc_200", 600, "linear"); 2638 $(this).removeClass('fn_expand', 600).html('Vis mindre'); 2639 } else { 2640 $(".longdesc_container").addClass("longdesc_200", 400); 2641 $(this).addClass('fn_expand',400).html('Læs mere'); 2642 } 2643 }); 2644 }); 2645 </script> 2646 2647 <script type="application/ld+json"> 2648 { 2649 "@@context" : "http://schema.org", 2650 "@@type" : "Product", 2651 "description" : "@Regex.Replace("" + GetString("Ecom:Product.ShortDescription"), "<[^>]*>", string.Empty).Replace("\"", "&quot;")", 2652 "sku" : "@GetString("Ecom:Product.Number")", 2653 "name" : "@GetString("Ecom:Product.Name")", 2654 "image" : "@( HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Host + GetString("Ecom:Product.ImageLarge.Clean") )", 2655 "offers" : { 2656 "@@type" : "Offer", 2657 "availability" : @( GetInteger( "Ecom:Product.Stock" ) > 0 ? "\"http://schema.org/InStock\"" : "\"http://schema.org/OutOfStock\"" ), 2658 "price" : "@String.Format("{0:0.00}", GetDouble("Ecom:Product.Price.Price")).Replace(",","." )", 2659 "priceCurrency" : "@GetString("Ecom:Product.Currency.Code")" 2660 } 2661 } 2662 </script>