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