Error executing template "Designs/Dwsimple/eCom/Product/Product.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at Hounisen.Website.Helpers.GroupHelper.GetParentsRecursively(Group group, List`1 groupNames)
at CompiledRazorTemplates.Dynamic.RazorEngine_32712abdde4b41a48537a7fef9af630b.Execute() in D:\web\hounisen\Hounisen.Website\Files\Templates\Designs\Dwsimple\eCom\Product\Product.cshtml:line 735
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 @using System.Web;
2 @using System.Net;
3 @using System.Globalization;
4 @using System.Text.RegularExpressions;
5 @using Dynamicweb;
6 @using Dynamicweb.Rendering;
7 @using Dynamicweb.Security.UserManagement;
8 @using System.IO;
9 @using Dynamicweb.Content
10 @using Dynamicweb.Core;
11 @using Dynamicweb.Ecommerce.Products
12 @using Hounisen.Website.Helpers
13 @using HtmlAgilityPack
14 @using VestjyskMarketing.Models;
15
16
17 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
18
19 @using System.Globalization
20 @using Dynamicweb.Content
21 @using Dynamicweb.Ecommerce
22 @using Dynamicweb.Ecommerce.Products
23 @using Dynamicweb.Security.UserManagement
24 @using Hounisen.Website.Helpers
25 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
26
27 @using System.Text.RegularExpressions
28 @using System.Web
29
30
31 @functions{
32 public class WrapMethods
33 {
34 //Gets the contrasting color
35 public static string getContrastYIQ(string hexcolor)
36 {
37 if (hexcolor != "")
38 {
39 hexcolor = Regex.Replace(hexcolor, "[^0-9a-zA-Z]+", "");
40
41 int r = Convert.ToByte(hexcolor.Substring(0, 2), 16);
42 int g = Convert.ToByte(hexcolor.Substring(2, 2), 16);
43 int b = Convert.ToByte(hexcolor.Substring(4, 2), 16);
44 int yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
45
46 if (yiq >= 128)
47 {
48 return "black";
49 }
50 else
51 {
52 return "white";
53 }
54 }
55 else
56 {
57 return "black";
58 }
59 }
60
61
62 //Truncate text
63 public static string Truncate (string value, int count, bool strip=true)
64 {
65 if (strip == true){
66 value = StripHtmlTagByCharArray(value);
67 }
68
69 if (value.Length > count)
70 {
71 value = value.Substring(0, count - 1) + "...";
72 }
73
74 return value;
75 }
76
77
78 //Strip text from HTML
79 public static string StripHtmlTagByCharArray(string htmlString)
80 {
81 char[] array = new char[htmlString.Length];
82 int arrayIndex = 0;
83 bool inside = false;
84
85 for (int i = 0; i < htmlString.Length; i++)
86 {
87 char let = htmlString[i];
88 if (let == '<')
89 {
90 inside = true;
91 continue;
92 }
93 if (let == '>')
94 {
95 inside = false;
96 continue;
97 }
98 if (!inside)
99 {
100 array[arrayIndex] = let;
101 arrayIndex++;
102 }
103 }
104 return new string(array, 0, arrayIndex);
105 }
106
107 //Make the correct count of columns
108 public static string ColumnMaker(int Col, string ScreenSize)
109 {
110 string Columns = "";
111
112 switch (Col)
113 {
114 case 1:
115 Columns = "col-"+ScreenSize+"-12";
116 break;
117
118 case 2:
119 Columns = "col-"+ScreenSize+"-6";
120 break;
121
122 case 3:
123 Columns = "col-"+ScreenSize+"-4";
124 break;
125
126 case 4:
127 Columns = "col-"+ScreenSize+"-3";
128 break;
129
130 default:
131 Columns = "col-"+ScreenSize+"-3";
132 break;
133 }
134
135 return Columns;
136 }
137
138
139 private string Custom(string firstoption, string secondoption)
140 {
141 if (firstoption == "custom")
142 {
143 return secondoption;
144 }
145 else
146 {
147 return firstoption;
148 }
149 }
150 }
151 }
152
153
154
155
156
157
158 @helper GetProductList(dynamic Loop, int ColMD = 3, int ColSM = 3, int ColXS = 1)
159 {
160 int Count = 0;
161
162 int index = 1;
163
164 var embeddedScript = GetString("Ecom:Group:Field.ProductEmbeddedScript");
165 var embedIndex = GetInteger("Ecom:Group:Field.EmbedScriptStartingIndex");
166
167 IFormatProvider jsNumberFormat = new NumberFormatInfo() { NumberDecimalSeparator = ".", NumberGroupSeparator = "" };
168
169
170 var groupService = new GroupService();
171 var productService = new ProductService();
172 var pageService = new PageService();
173
174 // SKI AND Region H
175 bool hasSkiDeal = false;
176 bool hasRegionHDeal = false;
177 var currentUser = User.GetCurrentExtranetUser();
178 if (currentUser != null)
179 {
180 var skiGroup = currentUser.Groups.FirstOrDefault(e => e.Name == "SKI");
181 if (skiGroup != null && !string.IsNullOrEmpty(skiGroup.Name))
182 {
183 hasSkiDeal = true;
184 }
185
186 hasRegionHDeal = Dynamicweb.Core.Converter.ToBoolean(currentUser.CustomFieldValues.Find(f => f.CustomField.SystemName == "AccessUser_RegionH").Value);
187 }
188
189
190 foreach (LoopItem product in Loop)
191 {
192 string GroupLink = "/Default.aspx?ID=" + product.GetString("Ecom:Product.PrimaryOrCurrentPageID") + "&groupid=" + product.GetString("Ecom:Product.PrimaryOrFirstGroupID") + "&productid=" + product.GetString("Ecom:Product.ID");
193 // string GroupLink = product.GetString("Ecom:Product.LinkGroup.Clean");
194 int stock = product.GetInteger("Ecom:Product.Stock");
195 string Name = product.GetString("Ecom:Product.Name");
196 string Description = product.GetString("Ecom:Product.ShortDescription");
197 string prodID = product.GetString("Ecom:Product.ID");
198 string prodVariantID = product.GetString("Ecom:Product.VariantID");
199 string prodLanguageID = product.GetString("Ecom:Product.LanguageID");
200 string Image = "/Admin/Public/GetImage.ashx?Image=/Files/Images/Ecom/Products/" + prodID + ".jpg&format=webp&quality=85";
201
202 //prices and units
203 string defaultUnitId = product.GetString("Ecom:Product.DefaultUnitID");
204 var prices = product.GetLoop("Product.Prices");
205 List<string> pricesHtmlList = Hounisen.Website.Helpers.Helpers.PricesListMakeListString(prices);
206 List<Hounisen.Website.Models.Unit> unitsDropdown = Hounisen.Website.Helpers.Helpers.PopulateUnitsDropdown(prices);
207 var unitDefault = unitsDropdown.Where(x => x.Id.Equals(defaultUnitId)).FirstOrDefault();
208 int minOrder = unitDefault != null ? unitDefault.MinOrder : 1;
209
210 if (!string.IsNullOrWhiteSpace(product.GetString("Ecom:Product.SelectedVariantComboID")))
211 {
212 prodID = product.GetString("Ecom:Product.ID") + "&" + product.GetString("Ecom:Product.SelectedVariantComboID");
213 }
214
215
216 GroupHelper gh = new GroupHelper();
217 var masterPage = pageService.GetPage(product.GetInteger("Ecom:Product.PrimaryOrCurrentPageID"));
218 masterPage.GetDisplayName();
219
220 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(product.GetString("Ecom:Product.PrimaryOrFirstGroupID"));
221 var groups = "";
222 if (group != null)
223 {
224 var groupNames = gh.GetParentsRecursively(group, new List<string>());
225 groupNames = gh.Format(groupNames, masterPage.GetDisplayName(), group);
226 groups = gh.ListToString(groupNames);
227 }
228
229 <div class="product-list__item">
230 <div class="col-xs-12">
231 <div class="product-list__item-inner">
232 <div class="col-xs-12 col-sm-4 col-flex">
233
234 <div class="product-list-item__primary-image">
235 @if (currentUser != null)
236 {
237 <a href="@GroupLink" title="@Name">
238 <img class="product-list-item__image lazy" alt="@Name" data-src="@Image&width=300" class="img-responsive img-center">
239 </a>
240 <a class="fancybox" data-fancybox href="@Image&width=1000" title="@Name">
241 <svg class="product-list-item__image-icon">
242 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/dist/icons/icons.svg#fullscreen"></use>
243 </svg>
244 </a>
245 }
246 else
247 {
248 <a href="@GroupLink" title="@Name">
249 <img class="product-list-item__image lazy" alt="@Name" data-src="@Image&width=300" class="img-responsive img-center">
250 </a>
251 <a class="fancybox" data-fancybox href="@Image&width=1000" title="@Name">
252 <svg class="product-list-item__image-icon">
253 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/dist/icons/icons.svg#fullscreen"></use>
254 </svg>
255 </a>
256 }
257
258
259 </div>
260 @{
261 var productObj = productService.GetProductById(prodID, prodVariantID, prodLanguageID);
262 var overlayNameAndColors = new ProductImageOverlayHelper().GetTextAndColor(productObj);
263
264 <div class="product__primary-image__overlay-container">
265 @foreach (var overlayNameAndColo in overlayNameAndColors)
266 {
267 <div style="background-color: @overlayNameAndColo.Value" class="product__primary-image__overlay-container__item">
268 @overlayNameAndColo.Key
269 </div>
270 }
271 </div>}
272 </div>
273 <div class="col-xs-12 col-sm-8">
274 <div class="product-list-item__info js-product-info">
275 <div class="row">
276 @*Title & Number*@
277 <div class="col-xs-12">
278 <h4 data-name="@Name" data-product_id="@prodID" data-categories="@groups" class="product-list-item__title">
279 <a class="product-list-item__title-link" href="@GroupLink">@Name</a>
280 </h4>
281 </div>
282 </div>
283 <div class="row">
284 <div class="col-xs-12 col-sm-5">
285
286 <div class="product-list-item__attributes">
287 <p>
288 <strong>Varenummer:</strong> @product.GetString("Ecom:Product.Number")
289 </p>
290 <p>
291 <strong>@product.GetString("Ecom:Product:Field.Attribut1A"):</strong><br/>@product.GetString("Ecom:Product:Field.Attribut1B")
292 </p>
293 <p>
294 <strong>@product.GetString("Ecom:Product:Field.Attribut2A"):</strong> @product.GetString("Ecom:Product:Field.Attribut2B")
295 </p>
296 </div>
297
298 <div class="hidden-xs">
299 <div class="">
300 @* IKONER *@
301 <div class="product-list-item__icons">
302 @{
303 foreach (var c in product.GetString("Ecom:Product:Field.Certificates").Split(','))
304 {
305 if (!string.IsNullOrEmpty(c))
306 {
307 string src = "/Admin/Public/GetImage.ashx?Image=/Files/Images/Ecom/Certificates/" + @c + ".jpg&format=webp&quality=85&width=100";
308 <img class="product-list-item__icon lazy" alt="@Translate("Cert_" + c, c)" title="@Translate("Cert_" + c, c)" data-src=@src src=@src>
309 }
310 }
311 }
312 </div>
313 </div>
314 </div>
315 </div>
316
317 <div class="col-xs-12 col-sm-7">
318 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")))
319 {
320 <ul class="product-list-item__prices">
321 @foreach (var priceHtml in pricesHtmlList)
322 {
323 <li>
324 @priceHtml
325 </li>
326 }
327 </ul>
328 }
329 </div>
330 </div>
331
332 <div class="row">
333 <div class="col-xs-12 col-sm-4 col-lg-5">
334 @* LAGERBEHOLDNING *@
335 <div class="product-list-item__stock">
336 @{
337 if (stock > 0)
338 {
339 <p class="product-list-item__stock-text">
340 <span class="product-list-item__stock-circle product-list-item__stock-circle--green"></span> På lager
341 </p>
342 }
343 else
344 {
345 <p class="product-list-item__stock-text">
346 <span class="product-list-item__stock-circle product-list-item__stock-circle--yellow"></span> Kontakt os for leveringstid: 86210800 eller salg@hounisen.com
347 </p>
348 }
349 }
350 </div>
351
352 <div class="product-list-item__see-product">
353 <a class="product-list-item__link" href="@GroupLink" class="">@Translate("See product", "Se produkt")</a>
354 </div>
355 </div>
356 <div class="col-xs-12 col-sm-8 col-lg-7">
357 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")))
358 {
359 <div class="row">
360 <div class="col-xs-7">
361 <div class="product__addtocart-input js-addtocart-input">
362 <input type="button" value="-" class="product-list-item__quantity-button product-list-item__quantity-button--minus qtyminus" field="quantity"/>
363 <input type="number" class="product__quantity-input product-list-item__quantity-input quantity" data-name="quantity" name="quantity" value="@minOrder" field="quantity"/>
364 <input type="button" value="+" class="product-list-item__quantity-button product-list-item__quantity-button--plus qtyplus" field="quantity"/>
365 </div>
366 <div class="product__unit-selector" style="display: inline-block;">
367 @{
368 int counter = 0;
369 }
370 @foreach (var unitDropdown in unitsDropdown)
371 {
372 var currentUnitPrice = prices[counter].Values["Ecom:Product.Prices.Amount"];
373 <input type="radio" data-id="@index" data-price="@currentUnitPrice" class="unit-type" id="@(unitDropdown.Id + prodID)" name="UnitID@(product.GetString("Ecom:Product.Number"))" value="@unitDropdown.Id" required data-lot-size="@unitDropdown.LotSize" data-min-order="@unitDropdown.MinOrder" @(unitsDropdown.Count == 1 ? "checked='checked'" : "")>
374 <label for="@(unitDropdown.Id + prodID)">@unitDropdown.Name</label>
375 counter++;
376 }
377 </div>
378 <p class="product__unit-selector-error-message">
379 @Translate("unit-error-message", "* Du mangler at vælge type")
380 </p>
381 </div>
382 <div class="col-xs-5">
383 <div class="product__addtocart-button">
384 <button data-id="@index" type="submit" name="submit" onclick="AddToCart(event, '@prodID', $(this).parent().parent().prev().find('input.quantity').val(), $(this).parent().parent().prev().find('input[name=\'UnitID@(product.GetString("Ecom:Product.Number"))\']:checked').val());" class="btn btn-primary product__button">
385 @Translate("Add to cart", "Add to cart")
386 <svg class="product__button-icon hidden-xs">
387 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/dist/icons/icons.svg#basket"></use>
388 </svg>
389 </button>
390 <div class="product-list-item__favorite-list popup-wrap favorite">
391
392 @if (hasRegionHDeal == false)
393 {
394 <button class="popup-show" data-popup="favorite-list" type="button" title="@Translate("Add to favorites", "Add to favorites")">
395 <i class="fa fa-star-o"></i> <span>Tilføj til liste</span>
396 </button>
397 <div id="favorite-list" class="popup-form">
398 <div class="close">
399 <i class="fa fa-times"></i>
400 </div>
401 <h3>@Translate("Choose list", "Choose list")</h3>
402 <ul>
403 @{
404 var lists = Dynamicweb.Ecommerce.CustomerCenter.CustomerProductList.GetListsByUserCustomerNumber(currentUser.CustomerNumber);
405 }
406
407 @foreach (var list in lists)
408 {
409 if (list.Products.Where(p => p.ProductId.ToString() == prodID).Count() > 0)
410 {
411 <li>
412 <a href="@(System.Web.HttpContext.Current.Request.Url)&CCRemoveFromMyLists=@prodID&CCAddToListVariantID=&CCAddToListLanguageID=LANG1&CCAddToListID=@list.ListId&CCListType=">
413 <i class="fa fa-star"></i> @list.Name
414 </a>
415 </li>
416 }
417 else
418 {
419 <li>
420 <a href="@(System.Web.HttpContext.Current.Request.Url)&CCAddToMyLists=@prodID&CCAddToListVariantID=&CCAddToListLanguageID=LANG1&CCAddToListID=@list.ListId&CCListType=">
421 <i class="fa fa-star-o"></i> @list.Name
422 </a>
423 </li>
424 }
425 }
426 <li>
427 <a href="/favoritter/opret-favoritliste?ProdID=@prodID">
428 <i class="fa fa-plus"></i>@Translate("Add new list", "Add new list")
429 </a>
430 </li>
431 </ul>
432 </div>
433 }
434
435 </div>
436 </div>
437 </div>
438 </div>
439 }
440 else
441 {
442 <div class="not-loggedin">
443 <p class="not-loggedin-text"><a data-toggle="modal" data-target="#login" href="">@Translate("Login", "Login")</a> eller <a href="/kontakt/opret-brugerprofil">Bliv kunde</a> for at se priser og købe på Hounisen.com</p>
444 <a data-toggle="modal" data-target="#login" href="" class="btn btn-primary not-loggedin-button">
445 <span>Log ind</span>
446 </a>
447 </div>
448 }
449 </div>
450 </div>
451 </div>
452
453
454 </div>
455 </div>
456 </div>
457 </div>
458
459 if (index == embedIndex)
460 {
461 <div class="product-list__item">
462 <div class="col-xs-12">
463 @embeddedScript
464 </div>
465 </div>
466 }
467
468
469 Count++;
470 index++;
471
472 if (Count == ColMD)
473 {
474 <div class="row"></div>
475 Count = 0;
476 }
477 }
478 }
479
480 <script>
481
482 document.addEventListener("DOMContentLoaded", function () {
483
484 var addToCartButtons = document.querySelectorAll('.product__button');
485 var unitTypes = document.getElementsByClassName("unit-type");
486 var product_names = document.getElementsByClassName("product-list-item__title");
487
488 addToCartButtons.forEach(function (item) {
489
490 item.addEventListener('click', function () {
491
492 var product_name = product_names[this.dataset.id - 1].dataset.name;
493 var product_id = product_names[this.dataset.id - 1].dataset.product_id;
494 var initialCategories = product_names[this.dataset.id - 1].dataset.categories;
495 var categories = initialCategories.split("_");
496 var quantity = document.getElementsByClassName("quantity")[this.dataset.id - 1].value;
497 var unitPrice;
498 var variantIsNull = true;
499 var unitTypeName = null;
500
501 //Get unittype price
502 for (const unitType of unitTypes) {
503
504 if (unitType.dataset.id == this.dataset.id) {
505
506 if (unitType.checked == true) {
507
508 var tempPrice = unitType.dataset.price.replace(".", "");
509 tempPrice = tempPrice.replace(",", ".");
510 unitPrice = parseFloat(tempPrice);
511 variantIsNull = false;
512 unitTypeName = unitType.value;
513
514 unitTypeName = unitTypeName.toString().split("_")[1];
515
516 }
517 }
518 }
519
520 if (!variantIsNull) {
521 dataLayer.push({ ecommerce: null });
522 dataLayer.push({
523 'event': 'add_to_cart',
524 "ecommerce": {
525 "currency": "DKK",
526 "value": unitPrice * parseInt(quantity).toFixed(2),
527 "items": [
528 {
529 "item_name": product_name + " - " + unitTypeName,
530 'item_id': product_id,
531 'price': unitPrice,
532 "item_brand": "",
533 "item_category": (categories[0] != null ? categories[0] : ""),
534 "item_category2": (categories[1] != null ? categories[1] : ""),
535 "item_category3": (categories[2] != null ? categories[2] : ""),
536 "item_category4": (categories[3] != null ? categories[3] : ""),
537 "item_category5": (categories[4] != null ? categories[4] : ""),
538 "quantity": parseInt(quantity),
539 }
540 ]
541 },
542
543 });
544 }
545 });
546 })
547 });
548
549 </script>
550 @using Dynamicweb.Security.UserManagement
551 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
552
553 @helper GetProductListRelated(dynamic Loop, int ColMD = 3, int ColSM = 3, int ColXS = 1)
554 {
555 var currentUser = User.GetCurrentExtranetUser();
556
557 <ul class="shop-list__list">
558
559 @foreach (LoopItem product in Loop)
560 {
561
562 string GroupLink = "/Default.aspx?ID=" + product.GetString("Ecom:Product.PrimaryOrCurrentPageID") + "&groupid=" + product.GetString("Ecom:Product.PrimaryOrFirstGroupID") + "&productid=" + product.GetString("Ecom:Product.ID");
563 string Name = product.GetString("Ecom:Product.Name");
564 string Description = product.GetString("Ecom:Product.ShortDescription");
565 string prodID = product.GetString("Ecom:Product.ID");
566 string Image = "/Admin/Public/GetImage.ashx?Image=/Files/Images/Ecom/Products/" + prodID + ".jpg&format=webp&quality=85";
567
568 <li class="shop-list__item col-xs-12">
569 <a class="shop-list__link" href="@GroupLink" title="@Name">
570 <figure class="shop-list__figure">
571 <img class="shop-list__image lazy" style="width: 213px;" alt="@Name" data-src="@Image&width=213">
572 </figure>
573 <h4 class="shop-list__title">@Name</h4>
574 <div class="shop-list__text">
575 @if (String.IsNullOrEmpty(product.GetString("Ecom:Product.LongDescription")))
576 {
577 var gr = Dynamicweb.Ecommerce.Products.Group.GetGroupById(product.GetString("Ecom:Product.PrimaryOrFirstGroupID"));
578
579 @gr.Description.Replace("<a ", "<span ").Replace("</a>", "</span>").Replace("<h2>", "<p>").Replace("</h2>", "</p>")
580 }
581 else
582 {
583 @product.GetString("Ecom:Product.LongDescription").Replace("<a ", "<span ").Replace("</a>", "</span>").Replace("<h2>", "<p>").Replace("</h2>", "</p>")
584 }
585
586 </div>
587 <div class="shop-list__price">
588 @if (currentUser != null)
589 {
590 string baseUnitPrice = String.Empty;
591 var price = product.GetLoop("Product.Prices").OrderBy(x => x.GetDouble("Ecom:Product.Prices.BaseUnitPrice")).FirstOrDefault();
592 if (price != null)
593 {
594 baseUnitPrice = price.GetString("Ecom:Product.Prices.BaseUnitPrice");
595 }
596 <span class="shop-list__price-from">Priser fra</span>
597 <span class="shop-list__price-value">@baseUnitPrice</span>
598 <span class="shop-list__price-unit">kr./stk.</span>
599 }
600 </div>
601 </a>
602 </li>
603
604 }
605 </ul>
606 }
607
608
609 @using Dynamicweb.Security.UserManagement
610 @using System.Text.RegularExpressions;
611 @using Hounisen.Website.Helpers
612 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
613
614 @helper GetProductListFullRelated(dynamic Loop, int ColMD = 4, int ColSM = 4, int ColXS = 1)
615 {
616 int Count = 0;
617
618 string ColumnsMD = WrapMethods.ColumnMaker(ColMD, "md");
619 string ColumnsSM = WrapMethods.ColumnMaker(ColSM, "sm");
620 string ColumnsXS = WrapMethods.ColumnMaker(ColXS, "xs");
621 var currentUser = User.GetCurrentExtranetUser();
622
623 foreach (LoopItem product in Loop)
624 {
625 string GroupLink = "/Default.aspx?ID=" + product.GetString("Ecom:Product.PrimaryOrCurrentPageID") + "&groupid=" + product.GetString("Ecom:Product.PrimaryOrFirstGroupID") + "&productid=" + product.GetString("Ecom:Product.ID");
626 string Name = product.GetString("Ecom:Product.Name");
627 string Description = GetFormattedDescription(product.GetString("Ecom:Product.LongDescription"));
628 string prodID = product.GetString("Ecom:Product.ID");
629 string Image = "/Admin/Public/GetImage.ashx?Image=/Files/Images/Ecom/Products/" + prodID + ".jpg&format=webp&quality=85";
630 var productObject = Dynamicweb.Ecommerce.Products.Product.GetProductById(product.GetString("Ecom:Product.ID"), product.GetString("Ecom:Product.VariantID"), product.GetString("Ecom:Product.LanguageID"));
631 var textAndColors = new ProductImageOverlayHelper().GetTextAndColor(productObject);
632 <li class="shop-list__item col-xs-12">
633 <a class="shop-list__link" href="@GroupLink" title="@Name">
634 <figure class="shop-list__figure" style="position: relative">
635 <img class="shop-list__image lazy" style="width: 213px;" alt="@Name" data-src="@Image&width=213">
636 <div class="product__primary-image__overlay-container">
637 @foreach (var overlayNameAndColor in textAndColors)
638 {
639 <div style="background-color: @overlayNameAndColor.Value" class="product__primary-image__overlay-container__item">
640 @overlayNameAndColor.Key
641 </div>
642 }
643 </div>
644 </figure>
645 <h4 class="shop-list__title">@Name</h4>
646 <div class="shop-list__text">@Description</div>
647 <div class="shop-list__price">
648 @if (currentUser != null)
649 {
650 string baseUnitPrice = String.Empty;
651 var price = product.GetLoop("Product.Prices").OrderBy(x => x.GetDouble("Ecom:Product.Prices.BaseUnitPrice")).FirstOrDefault();
652 if (price != null)
653 {
654 baseUnitPrice = price.GetString("Ecom:Product.Prices.BaseUnitPrice");
655 }
656
657 <span class="shop-list__price-from">Priser fra</span>
658 <span class="shop-list__price-value">@baseUnitPrice</span>
659 <span class="shop-list__price-unit">kr./stk</span>
660 }
661 </div>
662 </a>
663 </li>
664 }
665 }
666
667 @functions {
668 private static string GetFormattedDescription(string description = "")
669 {
670 string formattedDescription = Regex.Replace(description, @"<.*?>|[\r\n\t]| ", " ");
671 return formattedDescription.Length > 103 ? formattedDescription.Substring(0, 103).TrimEnd() + "..." : formattedDescription;
672 }
673 }
674
675 <script src="/Files/Templates/Designs/DwSimple/js/ProductVariantsAjax.js"></script>
676 <link rel="stylesheet" href="/Files/Templates/Designs/DwSimple/css/product.css"/>
677
678 @{
679 IFormatProvider jsNumberFormat = new NumberFormatInfo() { NumberDecimalSeparator = ".", NumberGroupSeparator = "" };
680 string initialPrice = string.Empty;
681 string metaDescription = string.Empty;
682 if (String.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")))
683 {
684 metaDescription = StripHTML(GetString("Ecom:Group.Description"));
685 }
686 else
687 {
688 metaDescription = StripHTML(GetString("Ecom:Product.LongDescription"));
689 }
690
691 bool isMobile = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Mobile;
692
693 //prices and units
694 string defaultUnitId = GetString("Ecom:Product.DefaultUnitID");
695 var prices = GetLoop("Product.Prices");
696 List<string> pricesHtmlList = Hounisen.Website.Helpers.Helpers.PricesListMakeListString(prices, false);
697 List<Hounisen.Website.Models.Unit> unitsDropdown = Hounisen.Website.Helpers.Helpers.PopulateUnitsDropdown(prices);
698 var unitDefault = unitsDropdown.Where(x => x.Id.Equals(defaultUnitId)).FirstOrDefault();
699 int minOrder = unitDefault != null ? unitDefault.MinOrder : 1;
700
701
702 //other vars
703 var pid = GetString("Ecom:Product.ID");
704 int stock = GetInteger("Ecom:Product.Stock");
705 string image = "/Admin/Public/GetImage.ashx?Image=/Files/Images/Ecom/Products/" + pid + ".jpg";
706 string productname = GetString("Ecom:Product.Name");
707 string productlink = "/Default.aspx?ID=" + GetString("Ecom:Product.PrimaryOrCurrentPageID") + "&groupid=" + GetString("Ecom:Product.PrimaryOrFirstGroupID") + "&productid=" + GetString("Ecom:Product.ID");
708
709
710 // SKI AND Region H
711 bool hasSkiDeal = false;
712 bool hasRegionHDeal = false;
713 var currentUser = User.GetCurrentExtranetUser();
714 if (currentUser != null)
715 {
716 var skiGroup = currentUser.Groups.FirstOrDefault(e => e.Name == "SKI");
717 if (skiGroup != null && !string.IsNullOrEmpty(skiGroup.Name))
718 {
719 hasSkiDeal = true;
720 }
721
722 hasRegionHDeal = Dynamicweb.Core.Converter.ToBoolean(currentUser.CustomFieldValues.Find(f => f.CustomField.SystemName == "AccessUser_RegionH").Value);
723 }
724
725 //serialized data
726 var pagedata = new System.Collections.Generic.Dictionary<String, Object>();
727 Pageview.Area.Item.SerializeTo(pagedata);
728
729
730 var pageService = new PageService();
731 GroupHelper gh = new GroupHelper();
732 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(GetString("Ecom:Product.PrimaryOrFirstGroupID"));
733 var masterPage = pageService.GetPage(GetInteger("Ecom:Product.PrimaryOrCurrentPageID"));
734 masterPage.GetDisplayName();
735 var groupNames = gh.GetParentsRecursively(group, new List<string>());
736 groupNames = gh.Format(groupNames, masterPage.GetDisplayName(), group);
737
738 var groups = gh.ListToString(groupNames);
739 }
740
741 <div class="col-md-12 col-sm-12 col-xs-12" style="margin-bottom: 25px">
742
743 <div class="row product" itemscope itemtype="http://schema.org/Product">
744 <section class="page-header" style="margin-top: 15px">
745 <div class="product__help-name-container">
746 <div class="col-xs-12 col-sm-7 p-0">
747 <meta itemprop="description" content="@metaDescription"/>
748 <h1 data-categories="@groups" data-group="@GetString("Ecom:Group.Name")" class="page-header__title" itemprop="name">@GetString("Ecom:Product.Name")</h1>
749 <div class="page-header__short-description">
750 <p class="product__number">@Translate("Productnumber", "Productnumber"): <span property="identifier" itemprop="mpn">@GetString("Ecom:Product.Number")</span></p>
751 @if (hasSkiDeal)
752 {
753 <p class="product__number">@Translate("Skinumber", "SKI nr"): <span property="identifier">@GetString("Ecom:Product:Field.SkiId")</span></p>
754 }
755 @if (hasRegionHDeal && GetBoolean("Ecom:Product:Field.RegionH"))
756 {
757 <p class="product__number">@Translate("RegionHText")</p>
758 }
759
760 </div>
761 </div>
762
763
764 <div class="d-none d-lg-block product__help-name-container__help p-0">
765 <div class="need-help product-view">
766 <img class="need-help__image lazy" width="81" height="81" data-src='@(Pageview.Area.Item["Support_Image"].ToString())?format=webp&width=81&quality=75'/>
767 <div class="need-help__text product-view">
768 @Pageview.Area.Item["Support_Content"].ToString()
769 </div>
770 </div>
771 </div>
772
773
774 </div>
775 </section>
776 <div class="row">
777
778 @* The image area *@
779 <div class="col-md-6 col-sm-4 col-xs-12 product__column">
780 <div class="product__gallery">
781
782 @* Discount sticker *@
783
784 @if (GetString("Ecom:Product.Discount.Price.PriceWithVATFormatted") != GetString("Ecom:Product.Price.PriceWithVATFormatted"))
785 {
786 if (pagedata["EcommerceStickerType"].ToString() == "ribbon")
787 {
788 <span class="ribbon base">@Translate("On sale!", "On sale!")</span>
789 }
790
791 if (pagedata["EcommerceStickerType"].ToString() == "ball")
792 {
793 <span class="ball">@Translate("On sale!", "On sale!")</span>
794 }
795 }
796
797
798 @* Product images *@
799 @{
800 string currenthost = HttpContext.Current.Request.Url.AbsoluteUri;
801 Uri uri = new Uri(currenthost);
802 currenthost = string.Format("{0}://{1}", uri.Scheme, uri.Authority);
803 string ImagePathloop = "";
804 string ImagePathClean = "";
805 string options = "format=webp&quality=85&width=1000";
806 List<string> imagepath = new List<string>();
807
808
809 //i starts at 1 - avoids showing the first image twice
810 for (int i = 1; i <= 5; i++)
811 {
812 ImagePathloop = "/Admin/Public/GetImage.ashx?Image=/Files/Images/Ecom/Products/" + pid + "-0" + i.ToString() + ".jpg";
813 //currenthost +
814 ImagePathClean = "/Files/Images/Ecom/Products/" + pid + "-0" + i.ToString() + ".jpg";
815
816 try
817 {
818 if (File.Exists(HttpContext.Current.Server.MapPath(ImagePathClean)))
819 {
820 imagepath.Add(ImagePathloop + "&" + options);
821 }
822
823 HttpWebRequest request = (HttpWebRequest)System.Net.WebRequest.Create(ImagePathloop);
824 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
825 {
826 if (response.StatusCode == HttpStatusCode.NotFound)
827 {
828 break;
829 }
830 else
831 {
832 imagepath.Add("/Files/Images/Ecom/Products/" + pid + "-0" + i.ToString() + ".jpg" + "" + options);
833 }
834 }
835 }
836 catch (Exception ex)
837 {
838 }
839 }
840 }
841
842 @{
843 var resizedImageLarge = VestjyskMarketing.Helpers.ImageHelper.ResizeImage(new ResizeImageSettings()
844 {
845 Image = $"/Files/Images/Ecom/Products/{pid}.jpg",
846 Width = 1000,
847 Quality = 99
848 });
849
850 var resizedImage = VestjyskMarketing.Helpers.ImageHelper.ResizeImage(new ResizeImageSettings()
851 {
852 Image = $"/Files/Images/Ecom/Products/{pid}.jpg",
853 Width = 458,
854 Quality = 85
855 });
856 }
857
858 <div class="product__primary-image">
859 <a href="@resizedImageLarge" data-fancybox="product-gallery" class="fancybox">
860 <img src="@resizedImage" data-src="@resizedImage" width="458" alt="@productname" class="product__image img-responsive lazy" itemprop="image">
861 @{
862 var productObj = new ProductService().GetProductById(GetString("Ecom:Product.ID"), GetString("Ecom:Product.VariantID"), GetString("Ecom:Product.LanguageID"));
863 var overlayNameAndColors = new ProductImageOverlayHelper().GetTextAndColor(productObj);
864 }
865
866 <div class="product__primary-image__overlay-container">
867 @foreach (var overlayNameAndColor in overlayNameAndColors)
868 {
869 <div style="background-color: @overlayNameAndColor.Value" class="product__primary-image__overlay-container__item">
870 @overlayNameAndColor.Key
871 </div>
872 }
873 </div>
874 <svg class="product__image-icon">
875 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/dist/icons/icons.svg#fullscreen"></use>
876 </svg>
877 </a>
878 </div>
879 <div class="row">
880 <div class="product__thumbnail-list">
881 @foreach (var imageThumb in imagepath)
882 {
883 <div class="col-sm-3 col-xs-4">
884 <div class="product__thumbnail-images">
885 <a href="@imageThumb&width=1000" data-fancybox="product-gallery" rel="product" class="fancybox">
886 <img data-src="@imageThumb&width=458" width="458" alt="@productname" class="img-responsive lazy">
887 </a>
888 </div>
889 </div>
890 }
891 @{
892 var youtubeId = GetString("Ecom:Product:Field.YoutubeId");
893 // For Fancybox, we typically include “?autoplay=1” in the iframe URL.
894 var youtubeEmbedUrl = $"https://www.youtube.com/embed/{youtubeId}?autoplay=1&enablejsapi=1";
895
896 if (!string.IsNullOrEmpty(youtubeId))
897 {
898 <div class="col-sm-3 col-xs-4">
899 <div class="product__thumbnail-images">
900 <a style="height: 63px" href="@youtubeEmbedUrl"
901 data-fancybox="product-gallery"
902 data-type="iframe"
903 rel="product"
904 class="fancybox">
905 <svg class="product__play-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
906 <path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zM188.3 147.1c7.6-4.2 16.8-4.1 24.3 .5l144 88c7.1 4.4 11.5 12.1 11.5 20.5s-4.4 16.1-11.5 20.5l-144 88c-7.4 4.5-16.7 4.7-24.3 .5s-12.3-12.2-12.3-20.9l0-176c0-8.7 4.7-16.7 12.3-20.9z"/>
907 </svg>
908 </a>
909 </div>
910 </div>
911 }
912
913 string mp4Path = GetString("Ecom:Product:Field.ProductVideo.FullPath");
914
915 if (!string.IsNullOrEmpty(mp4Path))
916 {
917 <div class="col-sm-3 col-xs-4">
918 <div class="product__thumbnail-images">
919 <!--
920 Link to a hidden <div> containing our <video>.
921 We use data-fancybox="product-gallery" to group it with our images.
922 data-src="#mp4VideoContent" + data-type="inline" to open inline HTML content.
923 -->
924 <a style="height: 63px" data-fancybox="product-gallery"
925 data-src="#mp4VideoContent"
926 data-type="inline"
927 href="javascript:;">
928 <svg class="product__play-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
929 <path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zM188.3 147.1c7.6-4.2 16.8-4.1 24.3 .5l144 88c7.1 4.4 11.5 12.1 11.5 20.5s-4.4 16.1-11.5 20.5l-144 88c-7.4 4.5-16.7 4.7-24.3 .5s-12.3-12.2-12.3-20.9l0-176c0-8.7 4.7-16.7 12.3-20.9z"/>
930 </svg>
931 </a>
932 </div>
933 </div>
934
935 <!-- Hidden HTML content that Fancybox will open -->
936 <div style="display:none;" id="mp4VideoContent">
937 <video controls style="width:100%; height:auto;">
938 <source src="@mp4Path" type="video/mp4"/>
939 <!-- You can add WebM or OGG sources if you like for broader browser support -->
940 Your browser does not support the video tag.
941 </video>
942 </div>
943 }
944 }
945 </div>
946 </div>
947 </div>
948 <section class="d-block d-lg-none page-header p-0 m-0" style="border: none">
949 <div class="product__help-name-container">
950 <div class=" product__help-name-container__help second">
951 <div class="need-help product-view">
952 <img class="need-help__image lazy" width="81" height="81" data-src='@(Pageview.Area.Item["Support_Image"].ToString())?format=webp&width=81&quality=75'/>
953 <div class="need-help__text product-view second">
954 @Pageview.Area.Item["Support_Content"].ToString()
955 </div>
956 </div>
957 </div>
958 </div>
959 </section>
960 </div>
961
962
963 @* The main product information area *@
964
965 <div class="col-md-6 col-sm-8 col-xs-12 product__column">
966 <div class="product-info js-product-info" id="productinfo">
967 <div class="product__control">
968 <div class="row">
969 <div class="col-xs-12 col-sm-6">
970 @* LAGERBEHOLDNING *@
971 <div class="product__stock">
972 @{
973 if (stock > 0)
974 {
975 <p class="product__stock-text">
976 <span class="product__stock-circle product__stock-circle--green"></span> På lager
977 </p>
978 }
979 else
980 {
981 <p class="product__stock-text">
982 <span class="product__stock-circle product__stock-circle--yellow"></span> Kontakt os for leveringstid: 86210800 eller salg@hounisen.com
983 </p>
984 }
985 }
986 </div>
987 </div>
988 <div class="col-xs-12 col-sm-6">
989 @* FAVORITTER *@
990 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")))
991 {
992 if (hasRegionHDeal == false)
993 {
994 <div class="product__favorite-list popup-wrap favorite">
995 <button class="popup-show" data-popup="favorite-list" type="button" title="@Translate("Add to favorites", "Add to favorites")">
996 <i class="fa fa-star-o"></i> <span>@Translate("Add to favorites", "Add to favorites")</span>
997 </button>
998 <div id="favorite-list" class="popup-form">
999 <div class="close">
1000 <i class="fa fa-times"></i>
1001 </div>
1002 <h3>@Translate("Choose list", "Choose list")</h3>
1003 <ul>
1004 @{
1005 var lists = Dynamicweb.Ecommerce.CustomerCenter.CustomerProductList.GetListsByUserCustomerNumber(currentUser.CustomerNumber);
1006 }
1007
1008 @foreach (var list in lists)
1009 {
1010 if (list.Products.Where(p => p.ProductId.ToString() == GetString("Ecom:Product.ID")).Count() > 0)
1011 {
1012 <li>
1013 <a href="@(System.Web.HttpContext.Current.Request.Url)&CCRemoveFromMyLists=@GetString("Ecom:Product.ID")&CCAddToListVariantID=&CCAddToListLanguageID=LANG1&CCAddToListID=@list.ListId&CCListType=">
1014 <i class="fa fa-star"></i> @list.Name
1015 </a>
1016 </li>
1017 }
1018 else
1019 {
1020 <li>
1021 <a href="@(System.Web.HttpContext.Current.Request.Url)&CCAddToMyLists=@GetString("Ecom:Product.ID")&CCAddToListVariantID=&CCAddToListLanguageID=LANG1&CCAddToListID=@list.ListId&CCListType=">
1022 <i class="fa fa-star-o"></i> @list.Name
1023 </a>
1024 </li>
1025 }
1026 }
1027 <li>
1028 <a href="/favoritter/opret-favoritliste?ProdID=@GetString("Ecom:Product.ID")">
1029 <i class="fa fa-plus"></i>@Translate("Add new list", "Add new list")
1030 </a>
1031 </li>
1032 </ul>
1033 </div>
1034 </div>
1035 }
1036 }
1037 else
1038 {
1039 <div class="not-loggedin">
1040 <p class="not-loggedin-text"><a data-toggle="modal" data-target="#login" href="">@Translate("Login", "Login")</a> eller <a href="/kontakt/opret-brugerprofil">Bliv kunde</a> for at se priser og købe på Hounisen.com</p>
1041 <a data-toggle="modal" data-target="#login" href="" class="btn btn-primary not-loggedin-button">
1042 <span>Log ind</span>
1043 </a>
1044 </div>
1045 }
1046 </div>
1047 </div>
1048
1049
1050 @* Prices and actions *@
1051 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")))
1052 {
1053 var product = GetString("Ecom:Product.ID");
1054 if (!string.IsNullOrWhiteSpace(GetString("Ecom:Product.SelectedVariantComboID")))
1055 {
1056 product = GetString("Ecom:Product.ID") + "&" + GetString("Ecom:Product.SelectedVariantComboID");
1057 }
1058
1059 <div class="row">
1060 <div class="col-xs-12">
1061 <ul class="product__prices">
1062 @foreach (var priceHtml in pricesHtmlList)
1063 {
1064 <li>
1065 @priceHtml
1066 </li>
1067 }
1068 </ul>
1069 </div>
1070 </div>
1071
1072 <div class="row">
1073 <div class="col-xs-7">
1074 <div class="product__addtocart-input js-addtocart-input">
1075 <input type="button" value="-" class="product__quantity-button product__quantity-button--minus qtyminus" field="quantity"/>
1076 <input type="number" class="product__quantity-input quantity" data-name="quantity" name="quantity" value="@minOrder" field="quantity"/>
1077 <input type="button" value="+" class="product__quantity-button product__quantity-button--plus qtyplus" field="quantity"/>
1078 </div>
1079 <div class="product__unit-selector" style="display: inline-block;">
1080
1081 @{
1082 var index = 0;
1083 }
1084
1085 @foreach (var unitDropdown in unitsDropdown)
1086 {
1087 index++;
1088 var currentUnitPrice = prices[index - 1].Values["Ecom:Product.Prices.Amount"];
1089 <input data-price="@currentUnitPrice" class="unit-type" type="radio" id="@unitDropdown.Id" name="UnitID" value="@unitDropdown.Id" required data-lot-size="@unitDropdown.LotSize" data-min-order="@unitDropdown.MinOrder" @(unitsDropdown.Count == 1 ? "checked='checked'" : "")>
1090 <label for="@unitDropdown.Id">@unitDropdown.Name</label>
1091 }
1092 </div>
1093 <p class="product__unit-selector-error-message">
1094 * Du mangler at vælge type
1095 </p>
1096 </div>
1097 <div class="col-xs-5">
1098 <div class="product__addtocart-button">
1099 <button type="submit" name="submit" onclick="AddToCart(event, '@product', $(this).parent().parent().prev().find('input.quantity').val(), $(this).parent().parent().prev().find('input[name=\'UnitID\']:checked').val());" class="btn btn-primary product__button">
1100 @Translate("Add to cart", "Add to cart")
1101 <svg class="product__button-icon hidden-xs">
1102 <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/dist/icons/icons.svg#basket"></use>
1103 </svg>
1104 </button>
1105 </div>
1106 </div>
1107 </div>
1108 }
1109 </div>
1110
1111 @* Product details *@
1112 <div>
1113 @* IKONER *@
1114 <div class="product__icons">
1115 @{
1116 foreach (var c in GetString("Ecom:Product:Field.Certificates").Split(','))
1117 {
1118 if (!string.IsNullOrEmpty(c))
1119 {
1120 <img class="product__icon lazy" data-src="/Files/Images/Ecom/certificates/@(c).jpg" title="@Translate("Cert_" + c, c)"/>
1121 }
1122 }
1123 }
1124
1125
1126 </div>
1127
1128
1129 </div>
1130 </div>
1131 </div>
1132 </div>
1133 </div>
1134 </div>
1135
1136
1137 @helper RenderDocuments()
1138 {
1139
1140 bool hasAtLeastOneLink =
1141 !string.IsNullOrEmpty(GetString("Ecom:Product:Field.Link1Label")) ||
1142 !string.IsNullOrEmpty(GetString("Ecom:Product:Field.Link2Label")) ||
1143 !string.IsNullOrEmpty(GetString("Ecom:Product:Field.Link3Label")) ||
1144 !string.IsNullOrEmpty(GetString("Ecom:Product:Field.Link4Label")) ||
1145 !string.IsNullOrEmpty(GetString("Ecom:Product:Field.Link5Label"));
1146 bool atleastOneProductDetail = hasAtLeastOneLink ||
1147 !string.IsNullOrEmpty(GetString("Ecom:Product:Field.Guidance.Value.Clean")) ||
1148 !string.IsNullOrEmpty(GetString("Ecom:Product:Field.FAQ.Value.Clean"));
1149
1150
1151
1152 @* DOWNLOAD *@
1153 if (hasAtLeastOneLink)
1154 {
1155 <div class="row">
1156 <div class="col-xs-12">
1157 <div onclick="updateDetailAccessibility(this)" class="product__section-container">
1158 <h3 class="product__header">@Translate("Dokumenter")</h3>
1159 <div class="product__section-container__icon-wrapper" data-height="0px" data-content-id="documents">
1160 <svg style="display: block" class="product__section-container__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
1161 <path d="M240 64c0-8.8-7.2-16-16-16s-16 7.2-16 16l0 176L32 240c-8.8 0-16 7.2-16 16s7.2 16 16 16l176 0 0 176c0 8.8 7.2 16 16 16s16-7.2 16-16l0-176 176 0c8.8 0 16-7.2 16-16s-7.2-16-16-16l-176 0 0-176z"/>
1162 </svg>
1163 <svg style="display: none" class="product__section-container__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
1164 <path d="M424 256c0 4.4-3.6 8-8 8L32 264c-4.4 0-8-3.6-8-8s3.6-8 8-8l384 0c4.4 0 8 3.6 8 8z"/>
1165 </svg>
1166 </div>
1167
1168 </div>
1169 </div>
1170 <div class="col-xs-12">
1171 <div style="display: block;">
1172 <div class="product__details">
1173 <div data-content-id="documents" class="product__details__content" style="max-height: 0px;">
1174
1175
1176 @if (GetString("Ecom:Product:Field.Link1Label") != "")
1177 {
1178 <div>
1179 <a class="product__download-pdf" target="_blank" href="@GetString("Ecom:Product:Field.Link1File.Clean")" class="">@GetString("Ecom:Product:Field.Link1Label")</a>
1180 </div>
1181 }
1182 @if (GetString("Ecom:Product:Field.Link2Label") != "")
1183 {
1184 <div>
1185 <a class="product__download-pdf" target="_blank" href="@GetString("Ecom:Product:Field.Link2File.Clean")" class="">@GetString("Ecom:Product:Field.Link2Label")</a>
1186 </div>
1187 }
1188 @if (GetString("Ecom:Product:Field.Link3Label") != "")
1189 {
1190 <div>
1191 <a class="product__download-pdf" target="_blank" href="@GetString("Ecom:Product:Field.Link3File.Clean")" class="">@GetString("Ecom:Product:Field.Link3Label")</a>
1192 </div>
1193 }
1194 @if (GetString("Ecom:Product:Field.Link4Label") != "")
1195 {
1196 <div>
1197 <a class="product__download-pdf" target="_blank" href="@GetString("Ecom:Product:Field.Link4File.Clean")" class="">@GetString("Ecom:Product:Field.Link4Label")</a>
1198 </div>
1199 }
1200 @if (GetString("Ecom:Product:Field.Link5Label") != "")
1201 {
1202 <div>
1203 <a class="product__download-pdf" target="_blank" href="@GetString("Ecom:Product:Field.Link5File.Clean")" class="">@GetString("Ecom:Product:Field.Link5Label")</a>
1204 </div>
1205 }
1206 </div>
1207 </div>
1208 </div>
1209 </div>
1210 </div>
1211 <hr class="product__hr"/>
1212 }
1213 }
1214
1215 @helper RenderGuidance()
1216 {
1217 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.Guidance.Value.Clean")))
1218 {
1219 <div class="row">
1220
1221 <div class="col-xs-12">
1222
1223
1224 <div onclick="updateDetailAccessibility(this)" class="product__section-container">
1225 <h3 class="product__header">Vejledning</h3>
1226
1227 <div class="product__section-container__icon-wrapper" data-height="0px" data-content-id="Guidance">
1228 <svg style="display: block" class="product__section-container__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
1229 <path d="M240 64c0-8.8-7.2-16-16-16s-16 7.2-16 16l0 176L32 240c-8.8 0-16 7.2-16 16s7.2 16 16 16l176 0 0 176c0 8.8 7.2 16 16 16s16-7.2 16-16l0-176 176 0c8.8 0 16-7.2 16-16s-7.2-16-16-16l-176 0 0-176z"/>
1230 </svg>
1231 <svg style="display: none" class="product__section-container__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
1232 <path d="M424 256c0 4.4-3.6 8-8 8L32 264c-4.4 0-8-3.6-8-8s3.6-8 8-8l384 0c4.4 0 8 3.6 8 8z"/>
1233 </svg>
1234 </div>
1235
1236 </div>
1237 </div>
1238 <div class="col-xs-12 py-4">
1239 <div style="display: block;">
1240 <div class="product__details">
1241 @{
1242 var text = GetString("Ecom:Product:Field.Guidance.Value.Clean");
1243 }
1244
1245 <div data-content-id="Guidance" class="product__details__content" style="max-height: 0px;">
1246 @text
1247 </div>
1248
1249 </div>
1250 </div>
1251 </div>
1252 </div>
1253
1254 <hr class="product__hr"/>
1255 }
1256 }
1257
1258 @helper RenderFAQ()
1259 {
1260 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.FAQ.Value.Clean")))
1261 {
1262 <div class="row">
1263
1264 <div class="col-xs-12">
1265
1266
1267 <div onclick="updateDetailAccessibility(this)" class="product__section-container">
1268 <h3 class="product__header">@Translate("FAQ")</h3>
1269
1270 <div class="product__section-container__icon-wrapper" data-height="0px" data-content-id="FAQ">
1271 <svg style="display: block" class="product__section-container__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
1272 <path d="M240 64c0-8.8-7.2-16-16-16s-16 7.2-16 16l0 176L32 240c-8.8 0-16 7.2-16 16s7.2 16 16 16l176 0 0 176c0 8.8 7.2 16 16 16s16-7.2 16-16l0-176 176 0c8.8 0 16-7.2 16-16s-7.2-16-16-16l-176 0 0-176z"/>
1273 </svg>
1274 <svg style="display: none" class="product__section-container__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
1275 <path d="M424 256c0 4.4-3.6 8-8 8L32 264c-4.4 0-8-3.6-8-8s3.6-8 8-8l384 0c4.4 0 8 3.6 8 8z"/>
1276 </svg>
1277 </div>
1278
1279 </div>
1280 </div>
1281 <div class="col-xs-12 py-4">
1282 <div style="display: block;">
1283 <div class="product__details">
1284 @{
1285 var text = GetString("Ecom:Product:Field.FAQ.Value.Clean");
1286 }
1287
1288 <div data-content-id="FAQ" class="product__details__content" style="max-height: 0px;">
1289 @text
1290 </div>
1291
1292 </div>
1293 </div>
1294 </div>
1295 </div>
1296
1297 <hr class="product__hr"/>
1298 }
1299 }
1300
1301 @helper RenderSpecifikationer()
1302 {
1303 <div class="row">
1304 <div class="col-xs-12">
1305 <hr class="product__hr"/>
1306 <div class="product__section-container product__section-container--no-hover">
1307 <h3 class="product__header">Specifikationer</h3>
1308 </div>
1309 </div>
1310 <div class="col-xs-12 py-4">
1311 <div style="display: block;">
1312 <div class="product__details">
1313
1314
1315 <div data-content-id="specifikationer" class="product__details__content" style="max-height: 9999px;">
1316
1317 @* ATTRIBUTTER *@
1318 <div class="product__information">
1319
1320 <dl class="product__information-table">
1321 @{
1322 int attributeLineCount = 0;
1323 for (int i = 1; i < 8; i++)
1324 {
1325 attributeLineCount++;
1326 string attributeName = "Ecom:Product:Field.Attribut" + attributeLineCount + "A";
1327 string attributeValue = "Ecom:Product:Field.Attribut" + attributeLineCount + "B";
1328 string attributeBrand = string.Empty;
1329
1330 if (GetString(attributeName) != "")
1331 {
1332 if (attributeLineCount == 7)
1333 {
1334 attributeBrand = "itemprop=\"brand\"";
1335 }
1336
1337 <dt>@GetString(attributeName) :</dt>
1338 <dd @attributeBrand>@GetString(attributeValue)</dd>
1339 }
1340 }
1341
1342 string manufacturerName = GetString("Ecom:Manufacturer.Name");
1343 string manufacturerUrl = GetString("Ecom:Manufacturer.Web");
1344
1345 if (!manufacturerName.IsNullOrEmpty() && !manufacturerUrl.IsNullOrEmpty())
1346 {
1347 <dt>Leverandør :</dt>
1348 <dd>
1349 <a target="_blank" class="product__information-table__manufacturer" href="@manufacturerUrl">@manufacturerName</a>
1350 </dd>
1351 }
1352 }
1353
1354 </dl>
1355 </div>
1356
1357
1358 </div>
1359
1360 </div>
1361 </div>
1362 </div>
1363 </div>
1364 }
1365
1366 @helper RenderDescription()
1367 {
1368 if (!String.IsNullOrEmpty(GetString("Ecom:Product.LongDescription")))
1369 {
1370 var description = GetString("Ecom:Product.LongDescription");
1371
1372 // Remove HTML tags
1373 string cleanedText = Regex.Replace(description, "<.*?>", " ");
1374 string[] words = cleanedText.Split(new[] { ' ', '\n', '\r', '\t' }, StringSplitOptions.RemoveEmptyEntries);
1375 bool readMoreButton = words.Length > 80;
1376
1377 <div class="row">
1378
1379 <div class="col-xs-12">
1380 <hr class="product__hr"/>
1381 <div onclick="updateDetailAccessibility(this)" class="product__section-container">
1382 <h3 style="@(!readMoreButton ? "cursor: auto" : "") " id="productLongDescriptionID" class="product__header">@Translate("Description", "Description")</h3>
1383
1384 <div class="product__section-container__icon-wrapper" data-height="95px" data-content-id="description">
1385
1386 @if (readMoreButton)
1387 {
1388 <svg style="display: block" class="product__section-container__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
1389 <path d="M240 64c0-8.8-7.2-16-16-16s-16 7.2-16 16l0 176L32 240c-8.8 0-16 7.2-16 16s7.2 16 16 16l176 0 0 176c0 8.8 7.2 16 16 16s16-7.2 16-16l0-176 176 0c8.8 0 16-7.2 16-16s-7.2-16-16-16l-176 0 0-176z"/>
1390 </svg>
1391 <svg style="display: none" class="product__section-container__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
1392 <path d="M424 256c0 4.4-3.6 8-8 8L32 264c-4.4 0-8-3.6-8-8s3.6-8 8-8l384 0c4.4 0 8 3.6 8 8z"/>
1393 </svg>
1394 }
1395 </div>
1396 </div>
1397 </div>
1398 <div class="col-xs-12 py-4">
1399 <div style="display: block;">
1400 <div class="product__details">
1401
1402 @if (readMoreButton)
1403 {
1404 <div data-content-id="description" class="product__details__content" style="min-height: 95px;max-height: 95px;">
1405 @description
1406 </div>
1407 }
1408 else
1409 {
1410 @description
1411 }
1412 </div>
1413 </div>
1414 </div>
1415 </div>
1416 }
1417 }
1418
1419
1420
1421
1422 <div class="row product__column__wrapper">
1423 <div class="col-md-6 col-sm-12 col-xs-12 product__column">
1424 @if (isMobile)
1425 {
1426 @RenderSpecifikationer()
1427 @RenderDescription()
1428 <hr class="product__hr"/>
1429 }
1430 else
1431 {
1432 @RenderDescription()
1433 <hr class="product__hr"/>
1434 @RenderGuidance()
1435 @RenderFAQ()
1436 }
1437
1438 </div>
1439 <div class="col-md-6 col-sm-12 col-xs-12 product__column">
1440 @if (isMobile)
1441 {
1442 @RenderDocuments()
1443 @RenderGuidance()
1444 @RenderFAQ()
1445 }
1446 else
1447 {
1448 @RenderSpecifikationer()
1449 <hr class="product__hr"/>
1450 @RenderDocuments()
1451 }
1452 </div>
1453 </div>
1454
1455
1456 @* Related products *@
1457
1458 @if (GetString("Ecom:Product.RelatedCount") != "0")
1459 {
1460 <div class="row">
1461 <div class="col-xs-12 p-15 p-md-0 @(isMobile ? "related-products-slider" : "")">
1462 <h2 class="product__header product__header--mobile-center">Relaterede varer</h2>
1463 <ul class="shop-list__list p-0-fc @(isMobile ? "owl-carousel" : "") ">
1464 @foreach (LoopItem relatedgroup in GetLoop("ProductRelatedGroups"))
1465 {
1466 var relatedproductloop = relatedgroup.GetLoop("RelatedProducts").OrderByDescending(g => g.GetString("Ecom:Product.LoopCounter")).Take(4).ToList();
1467 @GetProductListFullRelated(relatedproductloop, 3, 3, 1)
1468 }
1469 </ul>
1470 </div>
1471 </div>
1472 }
1473
1474
1475 <!-- Udforsk mere -->
1476
1477 @functions
1478 {
1479 List<int> GetIds(string idsRaw)
1480 {
1481 List<int> ids = new List<int>();
1482 if (idsRaw.IsNotNullOrEmpty())
1483 {
1484 foreach (var articleId in idsRaw.Split(','))
1485 {
1486 if (int.TryParse(articleId, out int id))
1487 {
1488 ids.Add(id);
1489 }
1490 }
1491 }
1492
1493 return ids;
1494 }
1495 }
1496
1497 @{
1498 var articlesPageId = GetPageIdByNavigationTag("ProductviewUniverseArticles");
1499 bool hasActiveArticles = false;
1500
1501 var productId = Dynamicweb.Context.Current.Request.QueryString["productid"];
1502 var defaultGroup = new ProductService().GetProductById(productId, "", true).DefaultGroup;
1503
1504 if (defaultGroup != null)
1505 {
1506 string articlesIdsRaw = defaultGroup.ProductGroupFieldValues.GetProductGroupFieldValue("Articles").Value.ToString();
1507 string articleSubGroupIdsRaw = defaultGroup.ProductGroupFieldValues.GetProductGroupFieldValue("ArticleSubCategories").Value.ToString();
1508
1509 List<int> articlesIds = new List<int>();
1510 if (!string.IsNullOrEmpty(articlesIdsRaw))
1511 {
1512 articlesIds = GetIds(articlesIdsRaw);
1513
1514 if (articlesIds.Count > 0)
1515 {
1516 hasActiveArticles = articlesIds.Any(x => new PageService().GetPage(x).Active);
1517 }
1518 }
1519
1520 if (!string.IsNullOrEmpty(articleSubGroupIdsRaw))
1521 {
1522 var subCategoryIds = GetIds(articleSubGroupIdsRaw);
1523
1524 List<string> subCategoryNames = new List<string>();
1525
1526 foreach (int subCategoryId in subCategoryIds)
1527 {
1528 var subCategory = new PageService().GetPage(subCategoryId);
1529 if (subCategory != null)
1530 {
1531 subCategoryNames.Add(subCategory.GetDisplayName());
1532 }
1533 }
1534
1535 foreach (string subCategoryName in subCategoryNames)
1536 {
1537 try
1538 {
1539 var subCategoryArticles = new PageService().GetPagesForItems(new List<string> { "UniverseArticlePage" }).Where(x => x.Item["SubCategories"].ToString().Contains(subCategoryName));
1540 if (subCategoryArticles.Any(x => x.Active))
1541 {
1542 hasActiveArticles = true;
1543 }
1544 }
1545 catch
1546 {
1547 }
1548 }
1549 }
1550 }
1551
1552 if (hasActiveArticles)
1553 {
1554 string articlesHeader = "";
1555 articlesHeader = defaultGroup.ProductGroupFieldValues.GetProductGroupFieldValue("ArticlesHeader").Value.ToString();
1556
1557 if (string.IsNullOrEmpty(articlesHeader))
1558 {
1559 articlesHeader = Translate("ProductViewArticleHeader");
1560 }
1561
1562 var paragraph = new ParagraphService().GetParagraphsByPageId(articlesPageId).FirstOrDefault();
1563
1564 if (paragraph != null)
1565 {
1566 <div class="row" style="margin-top: 15px">
1567 <div class="col-xs-12 p-15 p-md-0">
1568 <h2 class="product__header product__header--mobile-center articles">@articlesHeader</h2>
1569 </div>
1570
1571 </div>
1572
1573 <div class="row-25">
1574 @RenderParagraphContent(paragraph.ID)
1575 </div>
1576 }
1577 }
1578 }
1579
1580
1581 <div class="row p-15 p-md-0" style="margin-top: 15px">
1582 <!-- display block in clerk.js if at least one product -->
1583 <h2 class="product__header product__header--mobile-center" id="product-header-clerk" style="display: block;">Ofte købt sammen med</h2>
1584 <span class="clerk"
1585 data-template="@@product-page-others-also-bought"
1586 data-products='["@GetString("Ecom:Product.ID")"]'>
1587 </span>
1588 </div>
1589
1590
1591 <div class="row">
1592 <div class="col-md-12 col-sm-12 col-xs-12"> </div>
1593 </div>
1594
1595 @{
1596 var priceInitial = prices.Where(x => x.GetString("Ecom:Product.Prices.UnitID").Equals(unitDefault.Id)).OrderBy(x => x.GetDouble("Ecom:Product.Prices.Quantity")).FirstOrDefault();
1597
1598 CultureInfo us = new CultureInfo("en-US");
1599 string datalayerPriceInitial = string.Empty;
1600 if (priceInitial != null && Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName")))
1601 {
1602 datalayerPriceInitial = priceInitial.GetDouble("Ecom:Product.Prices.Amount").ToString("n", us).Replace(",", "");
1603 }
1604
1605 var pricesJs = new List<Dynamicweb.Ecommerce.LiveIntegration.Products.ProductPrice>();
1606 foreach (var priceJs in prices)
1607 {
1608 var productPrice = new Dynamicweb.Ecommerce.LiveIntegration.Products.ProductPrice();
1609 productPrice.BaseUnitPrice = priceJs.GetDouble("Ecom:Product.Prices.BaseUnitPrice");
1610 productPrice.PriceQuantityPerUnit = priceJs.GetDouble("Ecom:Product.Prices.PriceQuantityPerUnit");
1611 productPrice.Quantity = priceJs.GetDouble("Ecom:Product.Prices.Quantity");
1612 productPrice.UnitId = priceJs.GetString("Ecom:Product.Prices.UnitID");
1613 pricesJs.Add(productPrice);
1614 }
1615 }
1616
1617 @if (!String.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.ScriptsBottom")))
1618 {
1619 @SnippetStart("JavaScriptBottom")
1620 @GetString("Ecom:Product:Field.ScriptsBottom")
1621 @SnippetEnd("JavaScriptBottom")
1622 }
1623
1624 <script>
1625 var pricesJs = JSON.parse('@Newtonsoft.Json.JsonConvert.SerializeObject(pricesJs)');
1626
1627 // Create our number formatter.
1628 var formatterUs = new Intl.NumberFormat('en-US', {
1629 minimumFractionDigits: 2,
1630 });
1631
1632
1633
1634
1635 $('.product__addtocart-button').on('click', function () {
1636
1637 var quantityAdded = parseInt($(this).parent().prev().find('input.quantity').val());
1638 var unitAdded = $(this).parent().prev().find('select.unit').val();
1639 var priceFound = null;
1640 for (const key in pricesJs) {
1641 if (pricesJs[key].UnitId == unitAdded && quantityAdded >= parseInt(pricesJs[key].Quantity)){
1642 priceFound = pricesJs[key];
1643 }
1644 }
1645
1646 var priceAdded = 0;
1647 if (priceFound != null) {
1648 priceAdded = (priceFound.BaseUnitPrice * priceFound.PriceQuantityPerUnit) * quantityAdded; }
1649
1650 var quantity = document.getElementsByClassName("product__quantity-input")[0].value;
1651 var unitTypes = document.getElementsByClassName("unit-type");
1652 var isVariantNull = true;
1653
1654 var index = 0;
1655 var unitPrice;
1656 var currentUnitName;
1657 for (const button of unitTypes){
1658
1659 if (button.checked != false)
1660 {
1661 isVariantNull = false;
1662 var tempPrice = button.dataset.price.replace(".","");
1663 tempPrice = tempPrice.replace(",",".");
1664 unitPrice = parseFloat(tempPrice);
1665 currentUnitName = button.value.split("_")[1];
1666 index++;
1667 }
1668 }
1669
1670 if (!isVariantNull)
1671 {
1672 dataLayer.push({ecommerce:null});
1673 dataLayer.push({
1674 'event': 'add_to_cart',
1675 "ecommerce":{
1676 "currency" : "@GetString("Ecom:Product.CurrencyCode")",
1677 "value" : unitPrice * (parseInt(quantity)).toFixed(2),
1678 "items":[
1679 {
1680 "item_name": "@GetString("Ecom:Product.Name")" + " - " + currentUnitName,
1681 'item_id': '@GetString("Ecom:Product.ID")',
1682 'price': unitPrice,
1683 "item_brand" : "",
1684 "item_category": (categories[0] != null ? categories[0] : ""),
1685 "item_category2": (categories[1] != null ? categories[1] : ""),
1686 "item_category3": (categories[2] != null ? categories[2] : ""),
1687 "item_category4": (categories[3] != null ? categories[3] : ""),
1688 "item_category5": (categories[4] != null ? categories[4] : ""),
1689 "quantity": parseInt(quantity),
1690 }
1691 ]
1692 },
1693
1694 });
1695 }
1696
1697 });
1698
1699 //Sets the unittype if only one unittype for the product exists
1700 var types = document.getElementsByClassName("unit-type");
1701 var currentUnitName;
1702 var currentUnitPrice = 0;
1703
1704 if (types.length === 1){
1705 currentUnitName = " - " + (types[0].value.split("_")[1]);
1706 var tempPrice = types[0].dataset.price;
1707
1708 tempPrice = tempPrice.replace(".","");
1709 tempPrice = tempPrice.replace(",",".");
1710 currentUnitPrice = parseFloat(tempPrice);
1711
1712 }
1713 else{
1714 currentUnitName = "";
1715 }
1716
1717
1718
1719 var initialCategories = document.getElementsByClassName("page-header__title")[0].dataset.categories;
1720 var categories = initialCategories.split("_");
1721
1722
1723 // View_item initial
1724 dataLayer.push({ecommerce:null});
1725 dataLayer.push({
1726 'event': 'view_item',
1727 "ecommerce":{
1728 "currency" : "@GetString("Ecom:Product.CurrencyCode")",
1729 "value" : currentUnitPrice,
1730 "items":[
1731 {
1732 "item_name": "@GetString("Ecom:Product.Name")" + currentUnitName,
1733 'item_id': '@GetString("Ecom:Product.ID")',
1734 'price': currentUnitPrice,
1735 "item_brand" : "",
1736 "item_category": (categories[0] != null ? categories[0] : ""),
1737 "item_category2": (categories[1] != null ? categories[1] : ""),
1738 "item_category3": (categories[2] != null ? categories[2] : ""),
1739 "item_category4": (categories[3] != null ? categories[3] : ""),
1740 "item_category5": (categories[4] != null ? categories[4] : ""),
1741 "quantity": 1,
1742
1743 }
1744 ]
1745 },
1746
1747 });
1748
1749 var unitTypes = document.getElementsByClassName("unit-type");
1750
1751 var price;
1752 var oldPrice;
1753
1754 for (const btn of unitTypes)
1755 {
1756 btn.addEventListener("click", function () {
1757
1758
1759 tempPrice = this.dataset.price.replace(".","");
1760 tempPrice = tempPrice.replace(",",".");
1761 price = parseFloat(tempPrice);
1762
1763 currentUnitName = btn.value.split("_")[1];
1764
1765 //checks to see if the new variant is the same as the old one
1766 if (price != oldPrice){
1767
1768 dataLayer.push({ecommerce:null});
1769 dataLayer.push({
1770 'event': 'view_item',
1771 "ecommerce":{
1772 "currency" : "@GetString("Ecom:Product.CurrencyCode")",
1773 "value" : currentUnitPrice,
1774 "items":[
1775 {
1776 "item_name": "@GetString("Ecom:Product.Name")" + currentUnitName,
1777 'item_id': '@GetString("Ecom:Product.ID")',
1778 'price': currentUnitPrice,
1779 "item_brand" : "",
1780 "item_category": (categories[0] != null ? categories[0] : ""),
1781 "item_category2": (categories[1] != null ? categories[1] : ""),
1782 "item_category3": (categories[2] != null ? categories[2] : ""),
1783 "item_category4": (categories[3] != null ? categories[3] : ""),
1784 "item_category5": (categories[4] != null ? categories[4] : ""),
1785 "quantity": 1,
1786
1787 }
1788 ]
1789 },
1790
1791 });
1792
1793 }
1794 oldPrice = price;
1795 })
1796 }
1797
1798 </script>
1799
1800 @SnippetStart("JavaScriptBottom")
1801 <script type="text/javascript" src="~/Files/Templates/Designs/Dwsimple/js/video-api.js"></script>
1802
1803 @if (currentUser != null)
1804 {
1805 <script type="text/javascript" src="~/Files/Templates/Designs/Dwsimple/js/clerk.js"></script>
1806 }
1807
1808 <script>
1809 function on() {
1810 document.getElementById("overlay").style.display = "block";
1811 callPlayer('product-video', 'playVideo');
1812 }
1813 function off() {
1814 document.getElementById("overlay").style.display = "none";
1815 callPlayer('product-video', 'pauseVideo');
1816 }
1817 function updateDetailAccessibility(button) {
1818
1819 //set wrapper equal to first child of button with class product__section-container__icon-wrapper
1820 wrapper = button.parentElement.parentElement.querySelector('.product__section-container__icon-wrapper');
1821
1822
1823 var content = document.querySelector('.product__details__content[data-content-id="' + wrapper.getAttribute('data-content-id') + '"]');
1824 var defaultHeight = wrapper.getAttribute("data-height");
1825
1826 if (content.style.maxHeight == defaultHeight) {
1827 content.style.maxHeight = content.scrollHeight + "px";
1828 } else {
1829 content.style.maxHeight = defaultHeight;
1830 }
1831
1832 var icons = wrapper.querySelectorAll('.product__section-container__icon');
1833 icons.forEach(function(icon) {
1834 icon.style.display = icon.style.display === 'none' ? 'block' : 'none';
1835 });
1836
1837 }
1838
1839 </script>
1840
1841 @SnippetEnd("JavaScriptBottom")
1842
1843 @functions {
1844
1845 public static string StripHTML(string input)
1846 {
1847 var doc = new HtmlDocument();
1848 doc.LoadHtml(input);
1849 return doc.DocumentNode.InnerText;
1850 }
1851
1852 }
1853
1854
1855 <style>
1856
1857 .product__details {
1858 position: relative;
1859 margin-top: 10px;
1860 margin-bottom: 10px;
1861 p {
1862 margin: 0;
1863 width: fit-content;
1864 }
1865 a:hover{
1866 cursor: pointer;
1867 }
1868
1869 .product__details__content {
1870
1871
1872 overflow: hidden;
1873 transition: max-height 0.3s ease;
1874 }
1875
1876 }
1877
1878
1879 </style>