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&height=800&crop=5&FillCanvas=True&DoNotUpscale=true&Compression=75&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&height=200&crop=5&FillCanvas=True&DoNotUpscale=true&Compression=75&image=";
638 string imagePrefix = "/Admin/Public/GetImage.ashx?width=800&height=800&crop=5&FillCanvas=True&DoNotUpscale=true&Compression=75&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&height=50&crop=5&Compression=75&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&height=55&crop=5&FillCanvas=True&Compression=75&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&height=300&crop=5&Compression=75&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"> </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"> </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&height=220&crop=5&Compression=75&image={{image}}" alt="{{name}}" />
2342 <div class="u-margin-right {{noImage}}">
2343 <img src="/Admin/Public/GetImage.ashx?width=75&height=55&crop=5&FillCanvas=true&Compression=75&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("\"", """)",
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>