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