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