Prismatch på sammenlignelige varer i DanmarkPrismatch på sammenlignelige varer i Danmark
Bestil før kl. 14.00 - så sender vi i dagBestil før kl. 14.00 - så sender vi i dag
Danmarks største udvalg inden for NO DIGDanmarks største udvalg inden for NO DIG
Vi uddanner dig, inden du tager på opgaveVi uddanner dig, inden du tager på opgave
Error executing template "Designs/Rapido/eCom/Product/NZProductView.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_4f4fde10cf084ec3ac24e6f0859ff1f1.Execute() in E:\Solutions\S_DW_Lauridsen\lauridsen-live\Files\Templates\Designs\Rapido\eCom\Product\NZProductView.cshtml:line 559
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.DynamicWrapperService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at RazorEngine.Templating.RazorEngineServiceExtensions.RunCompile(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.RunCompile(IRazorEngineService service, ITemplateSource templateSource, String name, Type modelType, Object model, DynamicViewBag viewBag)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2 @using Dynamicweb.Extensibility 3 @using Dynamicweb.Content 4 @using System; 5 @using System.Globalization; 6 @using System.Linq 7 @using System.IO 8 @using Dynamicweb.Core 9 @using System.Web 10 @using Dynamicweb.Ecommerce 11 @using Dynamicweb.Ecommerce.Discounts 12 @using Dynamicweb.Ecommerce.Orders.Discounts 13 @using Dynamicweb.Ecommerce.Products 14 @using Dynamicweb.Ecommerce.Prices 15 @using NLog; 16 @using S_DW_Lauridsen.CustomCode 17 @using Dynamicweb.Security.UserManagement 18 @using NuGet.Versioning 19 @{ 20 21 string favoritPage = String.Format("/Default.aspx?ID={0}&CC20=CreateFormList", GetPageIdByNavigationTag("CustomerFavorites").ToString()); 22 string pageId = GetGlobalValue("Global:Page.ID").ToString(); 23 string productId = GetString("Ecom:Product.ID"); 24 string uniqueId = GetString("Ecom:Product.ID") + GetString("Ecom:Product.VariantID"); 25 // Stock status 26 int stockAmount = GetInteger("Ecom:Product.AvailableAmount"); 27 string currentPrice = GetString("Ecom:Product.Discount.Price.PriceFormatted") == GetString("Ecom:Product.Price.PriceFormatted") ? GetString("Ecom:Product.Price.PriceFormatted") : GetString("Ecom:Product.Discount.Price.PriceFormatted"); 28 string hideHelpText = ""; 29 string requestQuery = GetGlobalValue("Global:Request.Query"); 30 string variantId = HttpContext.Current.Request.QueryString.Get("variantId"); 31 string feedId = pageId + "&ProductID=" + productId + "&VariantID=" + variantId + "&Feed=True&redirect=false"; 32 //CFP bool 33 bool cfp = GetBoolean("Ecom:Product:Field.CFP"); 34 35 // Documents 36 string documentValue = GetString("Ecom:Product:Field.PDF_Path"); 37 var results = DocumentInfo.FileInformation(documentValue); 38 39 40 string externalLink = GetValue("Ecom:Product:Field.ExternalLinks.Value").ToString(); 41 var testList = externalLink.Split(new string[] { "</p>" }, StringSplitOptions.RemoveEmptyEntries).ToList(); 42 43 44 45 int featuresCount = 0; 46 string brand = GetString("Ecom:Product:Field.brand"); 47 bool onlyPreview = Converter.ToBoolean(Pageview.Area.Item["OnlyPreviewForAnonymous"]) && Pageview.User == null; 48 49 foreach (LoopItem customField in GetLoop("CustomFieldValues")) 50 { 51 if (!String.IsNullOrEmpty(customField.GetString("Product.CustomField.Value.Clean")) && customField.GetString("Product.CustomField.Name") != "CustomSticker") 52 { 53 featuresCount++; 54 } 55 } 56 57 foreach (LoopItem customField in GetLoop("ProductCategories")) 58 { 59 foreach (LoopItem field in customField.GetLoop("ProductCategoryFields")) 60 { 61 if (!String.IsNullOrEmpty(field.GetString("Ecom:Product.CategoryField.Value"))) 62 { 63 featuresCount++; 64 } 65 } 66 } 67 68 foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 69 { 70 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 71 { 72 if (variantoption.GetBoolean("Ecom:VariantOption.Selected")) 73 { 74 hideHelpText = "u-hidden"; 75 } 76 } 77 } 78 79 int relatedProductsPageSize = 4; 80 int relatedProductsColumnWidth = 3; 81 82 if (Pageview.Device.ToString() == "Mobile") 83 { 84 relatedProductsPageSize = 1; 85 relatedProductsColumnWidth = 12; 86 } 87 88 if (Pageview.Device.ToString() == "Tablet") 89 { 90 relatedProductsPageSize = 3; 91 relatedProductsColumnWidth = 4; 92 } 93 94 string pageNavTag = GetPageIdByNavigationTag("ProductsPage").ToString(); 95 string feedFullUrl = String.Format("/Default.aspx?ID={0}&PageSize={1}&ProdID={2}&feed=true", pageNavTag, relatedProductsPageSize, productId); 96 string relatedProductsFeed = String.Format("/Default.aspx?ID={0}&PageSize={1}&ProdID={2}&feed=true&RelateredeProdukter=", pageNavTag, relatedProductsPageSize, productId); 97 string productContainerId = "Product" + productId; 98 string video = GetString("Ecom:Product:Field.video"); 99 string siteURL = Dynamicweb.Context.Current.Request.Url.Scheme + "://" + Dynamicweb.Context.Current.Request.Url.Host; 100 Dynamicweb.Ecommerce.Products.Product currentProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(GetString("Ecom:Product.ID"), GetString("Ecom:Product.VariantID"), GetString("Ecom:Product.LanguageID")); 101 var imagePathValue = Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(currentProduct, "ImagePath"); 102 string imagePath = !string.IsNullOrWhiteSpace(imagePathValue.ToString()) ? "/Files/Images/Ecom/LHI_Products/Images/" + imagePathValue + ".jpg" : ""; 103 string productImage = !string.IsNullOrWhiteSpace(imagePath) ? imagePath : GetString("Ecom:Product.ImageLarge.Default.Clean"); 104 string canonicalURL = GetString("Ecom:Product.Canonical"); 105 106 //gallery 107 int imagesCount = 1; 108 List<string> galleryImages = new List<string>(); 109 110 galleryImages.Add(productImage); 111 if (!string.IsNullOrWhiteSpace(video)) 112 { 113 foreach (var image in video.Split('|')) 114 { 115 string videoThumb = String.Format("https://img.youtube.com/vi/{0}/0.jpg", image); 116 galleryImages.Add(videoThumb); 117 imagesCount++; 118 } 119 } 120 121 foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 122 { 123 if (!String.IsNullOrEmpty(alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"))) 124 { 125 string fullImage = "/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 126 galleryImages.Add(fullImage); 127 imagesCount++; 128 } 129 } 130 131 foreach (LoopItem detail in GetLoop("Details")) 132 { 133 string fullImage = "/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + detail.GetString("Ecom:Product:Detail.Image.Clean"); 134 135 if (!String.IsNullOrEmpty(fullImage)) 136 { 137 galleryImages.Add(fullImage); 138 imagesCount++; 139 } 140 } 141 142 string firstImage = galleryImages.FirstOrDefault(); 143 string galleryImagesArray = string.Join(", ", galleryImages); 144 } 145 146 @* Set product canonical URL *@ 147 @SnippetStart("canonical") 148 @{ 149 string host = GetGlobalValue("Global:Request.Host"); 150 string url = GetGlobalValue("Global:Pageview.Url"); 151 int queryIndex = url.IndexOf("?", StringComparison.Ordinal); 152 if (queryIndex > -1) 153 { 154 url = url.Substring(0, queryIndex); 155 } 156 } 157 <link rel="canonical" href="https://@host@url"> 158 @SnippetEnd("canonical") 159 <!-- Trigger for the gallery modal --> 160 <input type="checkbox" id="GalleryModalTrigger" class="modal-trigger" /> 161 162 <!-- Gallery modal --> 163 <div class="modal-container"> 164 <label for="GalleryModalTrigger" id="GalleryModalOverlay" class="modal-overlay"></label> 165 <div class="modal modal--lg modal--full modal-no-bg" id="GalleryModal"> 166 <div class="modal__body"> 167 <div class="gallery-slider js-gallery-slider" data-total-images="@imagesCount" data-images="@galleryImagesArray"> 168 <div class="gallery-slider__image"> 169 <img id="FullImage" src="@firstImage" class="w-100 js-video-button js-gallery-image" /> 170 </div> 171 <div class="gallery-slider__image-counter" id="FullImage_counter"> 172 </div> 173 <label class="gallery-slider__close-btn" for="GalleryModalTrigger"></label> 174 175 @if (imagesCount > 1) 176 { 177 <button class="gallery-slider__previous-btn" id="FullImage_prev" onclick="Gallery.prevImage('FullImage')"></button> 178 <button class="gallery-slider__next-btn" id="FullImage_next" onclick="Gallery.nextImage('FullImage')"></button> 179 } 180 181 </div> 182 </div> 183 </div> 184 </div> 185 186 <div class="paragraph-container__grid--bleed-x paragraph-container__grid--bleed-y product-view"> 187 <div class="grid product" id="productGrid"> 188 @* Image block with optional thumbs *@ 189 @if (!String.IsNullOrEmpty(productImage)) 190 { 191 <div class="grid__col-md-6 grid__col-sm-6"> 192 <div class="grid grid--bleed"> 193 @{ 194 int thumbCounter = 0; 195 } 196 <div class="grid__col-2 u-hidden-xxs dw-mod"> 197 <div class="carousel js-carousel-container u-max-h500px dw-mod"> 198 <div class="thumb-list carousel__container dw-mod m-0"> 199 <div class="carousel__container__slide carousel__container__slide--vertical dw-mod"> 200 201 @*Main image thumb*@ 202 <div class="carousel__container__slide dw-mod"> 203 <div class="thumb-list__item thumb-list__item--active dw-mod js-thumb js-thumb-btn js-gallery" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" data-image="/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&DoNotUpscale=true&amp;Compression=75&amp;image=@productImage"> 204 <label for="GalleryModalTrigger"> 205 <img src="/Admin/Public/GetImage.ashx?width=100&amp;height=100&amp;crop=5&amp;DoNotUpscale=true&amp;Compression=75&amp;image=@productImage" class="js-gallery" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="@thumbCounter" onclick="Gallery.openImage(this)" data-image="/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&DoNotUpscale=true&amp;Compression=75&amp;image=@productImage"> 206 </label> 207 </div> 208 </div> 209 210 @{ thumbCounter++; } 211 212 @foreach (LoopItem alternativeImage in GetLoop("Ecom:Product.AlternativeImages")) 213 { 214 if (!String.IsNullOrEmpty(alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"))) 215 { 216 string image = "/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 217 string thumb = "/Admin/Public/GetImage.ashx?width=100&amp;height=100&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + alternativeImage.GetString("Ecom:Product.AlternativeImages.Image"); 218 219 <div class="carousel__container__slide dw-mod"> 220 <div class="thumb-list__item dw-mod js-thumb-btn js-thumb js-gallery" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" data-image="@image"> 221 <label for="GalleryModalTrigger"> 222 <img src="@thumb" class="js-gallery" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="@thumbCounter" onclick="Gallery.openImage(this)" data-image="@image" data-src="@image"> 223 </label> 224 </div> 225 </div> 226 thumbCounter++; 227 } 228 } 229 230 @foreach (var youtubeLink in video.Split('|')) 231 { 232 if (!String.IsNullOrEmpty(youtubeLink)) 233 { 234 string image = String.Format("https://img.youtube.com/vi/{0}/0.jpg", youtubeLink.Split('?')); 235 string thumb = String.Format("https://img.youtube.com/vi/{0}/0.jpg", youtubeLink.Split('?')); 236 237 <div class="carousel__container__slide dw-mod"> 238 <a class="d-block thumb-list__item has-video dw-mod js-thumb js-thumb-btn js-video-button js-gallery" data-icon-nz="play" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" data-image="@image" href="@youtubeLink" data-type="youtube" data-toggle="modal"> 239 <label for="GalleryModalTrigger"> 240 <img src="@thumb" class="js-gallery" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="@thumbCounter" onclick="Gallery.openImage(this)" data-image="@image" data-src="@image"> 241 </label> 242 </a> 243 </div> 244 thumbCounter++; 245 } 246 } 247 248 @foreach (LoopItem detail in GetLoop("Details")) 249 { 250 if (!String.IsNullOrEmpty(detail.GetString("Ecom:Product:Detail.Image.Clean"))) 251 { 252 string image = "/Admin/Public/GetImage.ashx?width=550&amp;height=550&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + detail.GetString("Ecom:Product:Detail.Image.Clean"); 253 string thumb = "/Admin/Public/GetImage.ashx?width=100&amp;height=100&amp;crop=5&FillCanvas=True&DoNotUpscale=true&amp;Compression=75&amp;image=" + detail.GetString("Ecom:Product:Detail.Image.Clean"); 254 255 <div class="carousel__container__slide dw-mod"> 256 <div class="thumb-list__item dw-mod js-thumb-btn js-thumb js-gallery" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" data-image="@image"> 257 <label for="GalleryModalTrigger"> 258 <img src="@thumb" class="js-gallery" alt="@GetString("Ecom:Product.Name")" data-for="FullImage" data-number="@thumbCounter" onclick="Gallery.openImage(this)" data-image="@image" data-src="@image"> 259 </label> 260 </div> 261 </div> 262 thumbCounter++; 263 } 264 } 265 </div> 266 </div> 267 268 <div class="js-carousel-data" data-total-slides="@(imagesCount + 1)" data-carousel-slide-time="0" data-current-slide="0" data-direction="vertical" data-sliding-type="items" slides-in-view="6"> 269 <div class="carousel-prev-btn carousel-prev-btn--vertical dw-mod" onclick="Carousel.GetPreviousSlide(this)"></div> 270 <div class="carousel-next-btn carousel-next-btn--vertical dw-mod" onclick="Carousel.GetNextSlide(this)"></div> 271 </div> 272 273 </div> 274 </div> 275 276 <div class="grid__col-10"> 277 <div class="stickers-container dw-mod"> 278 @{ 279 if (Converter.ToBoolean(Pageview.Area.Item["EnableSaleTags"])) 280 { 281 string contentType = Pageview.Area.Item["EcommerceSaleTagContentType"].ToString(); 282 string text = ""; 283 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 284 285 switch (contentType) 286 { 287 case "Name": 288 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 289 { 290 text = discount.GetString("Ecom:Product.Discount.Name"); 291 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 292 } 293 break; 294 case "Amount": 295 if (GetLoop("ProductDiscounts").Count > 0) 296 { 297 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, GetDouble("Ecom:Product.Discount.Price.Price") - GetDouble("Ecom:Product.Price.Price")); 298 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 299 } 300 break; 301 case "Percents": 302 double percents = 0; 303 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 304 { 305 if (discount.GetDouble("Ecom:Product.Discount.ProductQuantity").Equals(1)) 306 { 307 percents = discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 308 } 309 } 310 if (percents > 0) 311 { 312 text = Math.Round(percents, 0) + "%"; 313 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 314 } 315 break; 316 case "Amount and percents": 317 double amount = 0; 318 double percent = 0; 319 foreach (LoopItem discount in GetLoop("ProductDiscounts")) 320 { 321 if (discount.GetString("Ecom:Product.Discount.Type") == "PERCENT") 322 { 323 percent += discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 324 } 325 else if (discount.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 326 { 327 amount += discount.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 328 } 329 } 330 if (percent > 0) 331 { 332 text = percent + "%"; 333 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 334 } 335 if (amount > 0) 336 { 337 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 338 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 339 } 340 break; 341 default: 342 if (GetLoop("ProductDiscounts").Count > 0) 343 { 344 text = Translate("Sale!"); 345 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 346 } 347 break; 348 } 349 } 350 351 if (Converter.ToBoolean(Pageview.Area.Item["NewStickersEnable"]) && GetDate("Ecom:Product.Created").AddDays(Converter.ToDouble(Pageview.Area.Item["NewStickersExpiration"])) > DateTime.Now) 352 { 353 <div class="stickers-container__tag stickers-container__tag--new dw-mod">@Translate("New!")</div> 354 } 355 356 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.CustomSticker.Value"))) 357 { 358 <div class="stickers-container__tag stickers-container__tag--custom dw-mod">@GetString("Ecom:Product:Field.CustomSticker.Value")</div> 359 } 360 } 361 </div> 362 363 <label for="GalleryModalTrigger" class="product__image-container"> 364 <img class="thumb-image-view product__image-container__image js-gallery-slider js-video-button dw-mod" src="/Admin/Public/GetImage.ashx?crop=5&width=550&height=550&Compression=75&image=@productImage" data-current-image="0" data-total-images="@imagesCount" data-images="@galleryImagesArray" data-src="/Admin/Public/GetImage.ashx?crop=5&width=550&height=550&Compression=75&image=@productImage" alt="@GetString("Ecom:Product.Name")" id="Image_@productId" data-for="FullImage" data-number="0" onclick="Gallery.openImageByNum(this)" /> 365 </label> 366 367 </div> 368 </div> 369 </div> 370 } 371 372 @* Primary product informations *@ 373 <div class="grid__col-12 grid__col-md-6 product__info dw-mod"> 374 <div> 375 <h1 class="product__title u-no-margin">@GetString("Ecom:Product.Name") @GetString("Ecom:Product.SelectedVariantComboName")</h1> 376 <small class="x-small text-gray-light font-weight-light">@(!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.Brand")) ? String.Format("{0}: {1}", Translate("Manufacturer"), GetString("Ecom:Product:Field.Brand")) : "") @Translate("product number"): @GetString("Ecom:Product.Number") @(!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.VVSNumber")) ? String.Format("{0}: {1}", Translate("VVS nr."), GetString("Ecom:Product:Field.VVSNumber")) : "") @(!string.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.DBN")) ? String.Format("{0}: {1}", Translate("DB nr."), GetString("Ecom:Product:Field.DBN")) : "") </small> 377 <div> 378 @* Delivery + stock information *@ 379 @if (onlyPreview) 380 { 381 <div> 382 <h5 class="mb-2">@Translate("LoginText", "Login")</h5> 383 <label for="SignInModalTrigger" class="btn btn--primary u-no-margin sign-in-modal-trigger-button dw-mod" onclick="setTimeout(function() { document.getElementById('LoginUsername').focus() }, 10)">@Translate("Sign in")</label> 384 </div> 385 } 386 387 @* Variants *@ 388 @if (GetLoop("VariantGroups").Count > 0) 389 { 390 string containerId = "Variants" + productId; 391 392 <div> 393 <div id="@containerId" data-product-id="@productId"> 394 @foreach (LoopItem variantGoup in GetLoop("VariantGroups")) 395 { 396 <div> 397 <div class="u-bold">@variantGoup.GetString("Ecom:VariantGroup.Name")</div> 398 <div> 399 @foreach (LoopItem variantOption in variantGoup.GetLoop("VariantAvailableOptions")) 400 { 401 string selected = variantOption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 402 403 if (!string.IsNullOrEmpty(variantOption.GetString("Ecom:VariantOption.ImgSmall.Clean"))) 404 { 405 <img src="/Admin/Public/GetImage.ashx?width=100&amp;height=50&amp;crop=5&amp;Compression=75&amp;image=/Images/@variantOption.GetString("Ecom:VariantOption.ImgSmall.Clean")" title="@variantOption.GetString("Ecom:VariantOption.Name")" id="@productId@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-product-id="@productId" onclick="Variants.UpdateVariants(this, false, true)" class="btn btn--tag @selected" data-check="@selected" /> 406 } 407 else 408 { 409 <button type="button" data-id="@GetString("Ecom:Product.ID")" id="@productId@variantOption.GetString("Ecom:VariantOption.ID")" data-variant-id="@variantOption.GetString("Ecom:VariantOption.ID")" data-product-id="@productId" onclick="Variants.UpdateVariants(this, false, true)" class="btn btn--tag @selected" data-check="@selected">@variantOption.GetString("Ecom:VariantOption.Name")</button> 410 } 411 } 412 </div> 413 </div> 414 } 415 </div> 416 <small id="helpText_@productId" class="help-text @hideHelpText">@Translate("Please select variant!")</small> 417 </div> 418 } 419 420 @* BOMProducts *@ 421 @if (GetLoop("BOMProducts").Count > 0) 422 { 423 <h2 class="section-title">@Translate("Including products")</h2> 424 foreach (LoopItem BOMProductItem in GetLoop("BOMProducts")) 425 { 426 string link = "/" + BOMProductItem.GetString("Ecom:Product.LinkGroup.Clean") + (!String.IsNullOrEmpty(BOMProductItem.GetString("Ecom:Product.VariantID")) ? "&VariantID=" + BOMProductItem.GetString("Ecom:Product.VariantID") : ""); 427 <div class="grid__col--border grid"> 428 <div class="grid__cell grid__cell--align-middle-left"> 429 <a href="@link" class="u-pull--left u-margin-right"> 430 <img src="/Admin/Public/GetImage.ashx?width=50&image=@BOMProductItem.GetString("Ecom:Product.ImageSmall.Default.Clean")&Compression=99" /> 431 </a> 432 <a href="@link">@BOMProductItem.GetString("Ecom:Product.Name")</a> 433 </div> 434 </div> 435 } 436 } 437 </div> 438 </div> 439 440 @* Buy block *@ 441 <div class="w-100 mt-5"> 442 <div class="js-handlebars-root dw-mod" id="PriceAndActions" data-template="PricesAndActionsTemplate" data-json-feed="/Default.aspx?ID=@feedId"></div> 443 <input type="hidden" value="@GetString("Ecom:Product.VariantID.Extented")" name="Variant" id="Variant_@GetString("Ecom:Product.ID")" /> 444 </div> 445 <div class="mt-4">@GetString("Ecom:Product:Field.LongDescription")</div> 446 <div class="product-page__specs">@ProductPropertiesMainArea()</div> 447 </div> 448 </div> 449 450 <section class="product-page__product-info"> 451 <div class="grid__col-12 grid__col-lg-9 m-auto"> 452 <div class="nav nav-pills nav-justified"> 453 <a class="nav-item nav-link js-toggle-class js-toggle-retrigger is-active" data-target-retrigger="target-retrigger" data-target=".product-page__content--description">@Translate("Product information")</a> 454 <a class="nav-item nav-link js-toggle-class js-toggle-retrigger" data-target-retrigger="target-retrigger" data-target=".product-page__content--video">@Translate("Documents/Video")</a> 455 <a class="nav-item nav-link js-toggle-class js-toggle-retrigger" data-target-retrigger="target-retrigger" data-target=".product-page__content--accessories">@Translate("Accessories")</a> 456 </div> 457 </div> 458 459 <div class="grid__col-12 grid__col-lg-10 m-auto grid__col--bleed-x"> 460 <div class="grid product-page__content product-page__content--description js-toggle-retrigger is-active"> 461 @* Features lists *@ 462 <div class="grid__col-12 grid__col-md-6 product__features dw-mod"> 463 <h1 class="h3 section-title">@Translate("Product information")</h1> 464 @GetString("Ecom:Product.LongDescription") 465 @GetString("Ecom:Product:Field.description") 466 </div> 467 <div class="grid__col-12 grid__col-md-6 product__features dw-mod"> 468 <h1 class="h3 section-title">@Translate("Product specs")</h1> 469 <div class="product-page__specs">@ProductProperties()</div> 470 </div> 471 </div> 472 <div class="grid product-page__content product-page__content--video js-toggle-retrigger justify-content-center"> 473 <div class="grid__col-12 grid__col-md-8 p-0 p-md-4"> 474 <h1 class="h3 section-title">@Translate("Documents/Video")</h1> 475 <div class="table-responsive small order-list"> 476 <table class="table table-striped product-page-table"> 477 <thead> 478 <tr> 479 <th class="font-weight-bold border-bottom-0" scope="col">@Translate("Name")</th> 480 <th class="font-weight-bold border-bottom-0" scope="col">@Translate("Type")</th> 481 <th class="font-weight-bold border-bottom-0" scope="col">@Translate("Size")</th> 482 </tr> 483 </thead> 484 <tbody> 485 486 @foreach (var documentPath in results) 487 { 488 <tr> 489 <td scope="row"> 490 <a href="@documentPath.FilePath" target="_blank"> 491 <img src="/Files/Images/Lauridsen/icons/icon-pdf.svg" class="product-page-table__icon d-inline-block align-middle mr-3" alt="@documentPath.FileName" /> 492 <span class="d-inline-block align-middle u-underline">@documentPath.FileName</span> 493 </a> 494 </td> 495 <td>@documentPath.FileType.Replace(".pdf", "PDF")</td> 496 <td>@documentPath.FileSize.ToSize(ByteExtension.SizeUnits.KB) KB</td> 497 </tr> 498 } 499 500 <tr> 501 502 @foreach (var youtubeLink in video.Split('|')) 503 { 504 if (!String.IsNullOrEmpty(youtubeLink)) 505 { 506 int thumbCounter = 0; 507 string image = String.Format("https://img.youtube.com/vi/{0}/0.jpg", youtubeLink); 508 string thumb = String.Format("https://img.youtube.com/vi/{0}/0.jpg", youtubeLink); 509 510 <td> 511 <div class="carousel__container__slide dw-mod"> 512 <a class="d-block dw-mod js-thumb-btn js-video-button" onmouseover="Gallery.openImage(this)" data-number="@thumbCounter" data-for="Image_@productId" href="@youtubeLink" data-type="youtube" data-toggle="modal"> 513 <label for="GalleryModalTrigger"> 514 <img src="/Files/Images/Lauridsen/icons/icon-video.svg" class="product-page-table__icon d-inline-block align-middle mr-4" alt="@GetString("Ecom:Product:Field.video")" /> 515 <span class="d-inline-block align-middle u-underline">@GetString("Ecom:Product:Field.video")</span> 516 </label> 517 </a> 518 </div> 519 </td> 520 <td>@GetString("Ecom:Product:Field.video.Name")</td> 521 <td>-</td> 522 thumbCounter++; 523 } 524 } 525 526 </tr> 527 528 @foreach (var value in testList) 529 { 530 531 if (externalLink.IsNotNullOrEmpty() && !string.IsNullOrWhiteSpace(value)) 532 { 533 <tr> 534 <td scope="row"> 535 <i class="product-page-table__icon d-inline-block align-middle mr-3 fa fa-link fa-2x"></i> 536 <span class="d-inline-block align-middle u-underline product-external-link">@value</span> 537 </td> 538 <td>@Translate("Link")</td> 539 <td>-</td> 540 </tr> 541 } 542 } 543 </tbody> 544 </table> 545 </div> 546 </div> 547 </div> 548 <div class="grid product-page__content product-page__content--accessories js-toggle-retrigger"> 549 <h1 class="h3 section-title">@Translate("Accessories")</h1> 550 <div class="grid accessories-list dw-mod"> 551 <form name="multiForm" id="multiForm" class="accessories-list__form js-load-more-container" data-initial-load="5" method="post"> 552 <input type="hidden" name="CartCmd" id="CartCmd" value="addMulti" /> 553 @{ 554 string currentShopId = Converter.ToBoolean(Pageview.Area.Item["LRT_Theme"]) ? "SHOP10" : "SHOP8"; 555 List<Product> accessoriesProducts = new List<Product>(); 556 557 558 List<Dynamicweb.Ecommerce.Products.Group> parentGroups = Services.Shops.GetShop(currentShopId.ToString()).TopLevelGroups.ToList(); 559 string getGroup = currentProduct.DefaultGroup.ParentGroups.FirstOrDefault().Name; 560 561 Dynamicweb.Ecommerce.Products.Group topGroup = parentGroups.FirstOrDefault(groupName => groupName.Name.Contains(getGroup)); 562 563 Dynamicweb.Ecommerce.Products.Group accessoriesGroup = topGroup != null && topGroup.Subgroups.Any() ? topGroup.Subgroups.FirstOrDefault(x => x.Name.Equals("Tilbehør")) : null; 564 565 if (currentProduct.DefaultGroup != accessoriesGroup && accessoriesGroup != null && accessoriesGroup.Products.Any()) 566 { 567 accessoriesProducts = accessoriesGroup.Products.ToList(); 568 } 569 } 570 @if (accessoriesProducts.Any() && currentProduct.DefaultGroup.ParentGroups.FirstOrDefault().Name != null) 571 { 572 foreach (var accessoriesProduct in accessoriesProducts) 573 { 574 uniqueId = accessoriesProduct.Id; 575 string onSale = !Converter.ToBoolean(Pageview.Area.Item["EnableSaleTags"]) || accessoriesProduct.Discounts.Price.PriceFormatted == accessoriesProduct.Price.PriceFormatted ? "u-hidden" : ""; 576 string newSticker = Pageview.Area.Item["NewStickersEnable"].ToString() == "True" && accessoriesProduct.Created.AddDays(Converter.ToDouble(Pageview.Area.Item["NewStickersExpiration"])) > DateTime.Now ? "" : "u-hidden"; 577 string link = "Default.aspx?" + "ID=" + GetInteger("Ecom:Product.PrimaryOrCurrentPageID") + "&GroupID=" + accessoriesGroup.IdUrlEncoded + "&ProductID=" + accessoriesProduct.Id; 578 bool hasVariants = accessoriesProduct.VariantCount > 0 ? true : false; 579 string price = accessoriesProduct.Discounts.Price.PriceFormatted != accessoriesProduct.Price.PriceFormatted ? accessoriesProduct.Discounts.Price.PriceFormatted : accessoriesProduct.Price.PriceFormatted; 580 string discount = accessoriesProduct.Discounts.Price.PriceFormatted != accessoriesProduct.Price.PriceFormatted ? accessoriesProduct.Price.PriceFormatted : ""; 581 bool hasUnits = accessoriesProduct.Units.Count > 0 ? true : false; 582 var firstAccessoriesProductPrice = accessoriesProduct.Prices.Any() ? accessoriesProduct.Prices.FirstOrDefault() : null; 583 var accessoriesImagePath = Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(accessoriesProduct, "ImagePath"); 584 string accessoriesProductImage = !string.IsNullOrWhiteSpace(accessoriesImagePath.ToString()) ? "/Files/Images/Ecom/LHI_Products/Images/" + accessoriesImagePath + ".jpg" : accessoriesProduct.ImageLarge; 585 List<Dynamicweb.Security.UserManagement.Group> userGroups = new List<Dynamicweb.Security.UserManagement.Group>(); 586 bool userisLoggedIn = Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn(); 587 bool isEmpty = !userGroups.Any(); 588 string stickerValue = string.Empty; 589 string stockText = ""; 590 var getDiscount = accessoriesProduct.GetDiscountMatrix("", "").FirstOrDefault(x => x.Discount.ProductsAndGroupsIds.Equals(accessoriesProduct.Id)); 591 if (accessoriesProduct.Stock > 5) 592 { 593 stockText = @Translate("In Stock"); 594 } 595 else if (accessoriesProduct.Stock <= 5 && accessoriesProduct.Stock > 1) 596 { 597 stockText = @Translate("Few in stock"); 598 } 599 else 600 { 601 stockText = @Translate("Not in stock"); 602 } 603 604 605 if (isEmpty && Dynamicweb.Security.UserManagement.User.IsExtranetUserLoggedIn()) 606 { 607 userGroups = Dynamicweb.Security.UserManagement.User.GetCurrentExtranetUser().Groups.ToList(); 608 } 609 string imageUrl = "/Files/Images/missing_image.jpg"; 610 if (!string.IsNullOrEmpty(accessoriesProductImage)) 611 { 612 imageUrl = accessoriesProductImage; 613 } 614 <div class="accessories-list__item accessorie grid__col-12 grid__col--bleed-x js-load-more-item is-hidden"> 615 <div class="grid"> 616 <figure class="grid__col-sm-2 grid__col-12 accessorie__figure"> 617 <div class="stickers-container"> 618 <div class="stickers-container__tag stickers-container__tag--new @newSticker dw-mod">@Translate("New!")</div> 619 @if (accessoriesProduct.GetDiscountMatrix("", "").Any() && Converter.ToBoolean(Pageview.Area.Item["EnableSaleTags"])) 620 { 621 if (getDiscount != null) 622 { 623 stickerValue = getDiscount.Discount.Percentage.ToString(); 624 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@stickerValue</div> 625 } 626 } 627 </div> 628 <div class="grid__cell"> 629 <a href="@link" onclick="Scroll.SavePosition(event)" title="@accessoriesProduct.Name"> 630 <img class="grid__cell-img accessorie__image" 631 src="/Admin/Public/GetImage.ashx?width=350&amp;height=350&amp;crop=5&amp;Compression=75&amp;DoNotUpscale=true&amp;image=@imageUrl" 632 alt="@accessoriesProduct.Name" /> 633 </a> 634 </div> 635 </figure> 636 <div class="grid__col-12 grid__col-sm-4 accessorie__description"> 637 <a class="" href="@link" onclick="Scroll.SavePosition(event)" title="@accessoriesProduct.Name"> 638 <div class="accessorie__number"><b>Vare nr.</b> @accessoriesProduct.Number</div> 639 <h3 class="accessorie__name">@accessoriesProduct.Name</h3> 640 <div class="accessorie__text">@accessoriesProduct.ShortDescription</div> 641 <div class="product-list-item__stock"> 642 <div class="stock-icon ml-0 @(accessoriesProduct.Stock > 0 ? "stock-icon--in" : "stock-icon--not")"></div> 643 <span>@stockText</span> 644 </div> 645 <span class="product-card__quantity-alert js-product-quantity-error-@accessoriesProduct.Id ">@Translate("Max stock level is reached")</span> 646 </a> 647 </div> 648 649 @if (!onlyPreview) 650 { 651 List<Price> priceCollectionList = new List<Price>(); 652 List<Price> getLowestPriceList = new List<Price>(); 653 List<Price> orderedPriceList = new List<Price>(); 654 List<Price> getPriceCollection = new List<Price>(); 655 656 if (userisLoggedIn) 657 { 658 if (accessoriesProduct.Prices.ToList().Any()) 659 { 660 priceCollectionList = accessoriesProduct.Prices.ToList(); 661 } 662 663 string userPriceGroups = string.Empty; 664 if (userGroups.Any()) 665 { 666 <div class=" grid__col-12 grid__col-sm-3 accessorie__details" style="text-align: center"> 667 @foreach (Price priceItem in priceCollectionList.Where(priceItem => priceItem.ProductId.Equals(uniqueId))) 668 { 669 foreach (Dynamicweb.Security.UserManagement.Group userGroupItem in userGroups.Where(userGroup => userGroup.ID.Equals(Int32.Parse(priceItem.UserGroupId)))) 670 { 671 userPriceGroups = userGroupItem.ID.ToString(); 672 if (userPriceGroups != null && priceCollectionList != null) 673 { 674 Price getLowest = priceCollectionList.Where(priceGroup => priceGroup.UserGroupId.Contains(userPriceGroups)).OrderBy(sortQuantity => sortQuantity.Quantity).ThenBy(sortOrder => sortOrder.Amount).ToList().FirstOrDefault(); 675 getLowestPriceList.Add(getLowest); 676 getPriceCollection = priceCollectionList.Where(priceGroup => priceGroup.UserGroupId.Contains(userPriceGroups)).ToList(); 677 if (getPriceCollection.Exists(check => check.Quantity > 2) && getPriceCollection != null) 678 { 679 orderedPriceList.Add(getPriceCollection.FirstOrDefault()); 680 } 681 } 682 } 683 } 684 @if (userPriceGroups != null && getLowestPriceList.Any()) 685 { 686 Price getLowestPrice = getLowestPriceList.OrderBy(lowerPrice => lowerPrice.Amount).ToList().FirstOrDefault(); 687 if (getLowestPrice.Quantity < 2) 688 { 689 double DiscountPercentage = 0; 690 691 if (accessoriesProduct.GetDiscountMatrix("", "").Count >= 1) 692 { 693 DiscountInfo discountInfos = accessoriesProduct.GetDiscountMatrix("", "").Where(discounts => discounts.Discount.ProductsAndGroupsIds.Equals(accessoriesProduct.Id) && discounts.Discount.ProductQuantity.Equals(1)).OrderByDescending(quantity => quantity).FirstOrDefault(); 694 695 if (discountInfos != null) 696 { 697 double percentageCalculation = discountInfos.Discount.Percentage / 100; 698 DiscountPercentage = getLowestPrice.Amount - (getLowestPrice.Amount * percentageCalculation); 699 if (accessoriesProduct.GetDiscountMatrix("", "").Any()) 700 { 701 <div class="accessorie__price price">@getLowestPrice.Currency.Symbol @DiscountPercentage</div> 702 } 703 } 704 } 705 706 if (DiscountPercentage == 0) 707 { 708 <div class="accessorie__price price">@getLowestPrice.Currency.Symbol @getLowestPrice.Amount</div> 709 } 710 <div class=""> 711 @Translate("UnitPriceText") @getLowestPrice.Quantity @Translate("UnitPriceTextStk") 712 </div> 713 } 714 715 if (getPriceCollection.Exists(check => check.Quantity > 2) && orderedPriceList.Any()) 716 { 717 <div class="js-popup"> 718 <a class="js-popup-trigger">@Translate("DiscountText")</a> 719 <div class="js-popup-modal popup_productrelatedview"> 720 <div class="js-popout-close nz-icon icon-nz-close-circled"></div> 721 <ul class="grid__col-12 pt-5 p-0 d-flex flex-row flex-wrap"> 722 @foreach (Price prices in orderedPriceList.OrderBy(priceMatrix => priceMatrix.Quantity)) 723 { 724 <li class="grid__col-lg-6 p-0 mb-0 grid__col-12 align-items-center align-items-xl-start">@Translate("UnitPriceText") @prices.Quantity @Translate("UnitPriceTextStk")</li> 725 <li class="grid__col-lg-6 p-0 pb-3 grid__col-12 align-items-center align-items-xl-end">@prices.Amount.ToString("C")</li> 726 } 727 </ul> 728 </div> 729 </div> 730 } 731 } 732 733 </div> 734 if (getLowestPriceList.Any()) 735 { 736 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 737 <div class="accessorie__controls-inner"> 738 <div class="accessorie__button-container d-inline-block"> 739 <button type="button" id="CartButton_@accessoriesProduct.Id" class="btn btn--primary accessorie__cart" name="submit" onclick="Cart.AddToCart(event, '@accessoriesProduct.Id', document.getElementById('Quantity_@accessoriesProduct.Id').value, 'Unit_@accessoriesProduct.Id', 'Variant_@accessoriesProduct.Id');"> 740 <i class="fa fa-shopping-cart"></i> 741 <span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span> 742 </button> 743 </div> 744 745 <div class="product-card__quantity--condenced product-card__quantity accessorie__quantity"> 746 <input id="Quantity_@accessoriesProduct.Id" class="product-card__quantity-input pointer-events js-quantity-input" name="Quantity@accessoriesProduct.Id" data-id="@accessoriesProduct.Id" type="number" min="1" max="@accessoriesProduct.Stock" value="1"> 747 <span class="product-card__quantity-add js-product-quantity-add" data-icon-nz="chevron-up"></span> 748 <span class="product-card__quantity-subtract js-product-quantity-subtract" data-icon-nz="chevron-down"></span> 749 </div> 750 751 </div> 752 </div> 753 } 754 else 755 { 756 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 757 <div class="accessorie__controls-inner"> 758 <div class="accessorie__button-container d-inline-block"> 759 <button type="button" id="CartButton_@accessoriesProduct.Id" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" name="submit" data-target=".js-target"> 760 <span class="u-hidden-xs u-hidden-xxs"> @Translate("CallForPrice")</span> 761 </button> 762 </div> 763 </div> 764 </div> 765 } 766 } 767 else 768 { 769 <div class=" grid__col-12 grid__col-sm-3 accessorie__details" style="text-align: center"> 770 <div class="accessorie__price price"></div> 771 <div class="accessorie__before-price before-price "></div> 772 <div class=""> 773 </div> 774 <div class="js-popup"> 775 <div class="js-popup-modal popup_productrelatedview"> 776 <div class="js-popout-close nz-icon icon-nz-close-circled"></div> 777 </div> 778 </div> 779 </div> 780 if (getLowestPriceList.Any()) 781 { 782 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 783 <div class="accessorie__controls-inner"> 784 785 <div class="accessorie__button-container d-inline-block"> 786 <button type="button" id="CartButton_@accessoriesProduct.Id" class="btn btn--primary accessorie__cart" name="submit" onclick="Cart.AddToCart(event, '@accessoriesProduct.Id', document.getElementById('Quantity_@accessoriesProduct.Id').value, 'Unit_@accessoriesProduct.Id', 'Variant_@accessoriesProduct.Id');"> 787 <i class="fa fa-shopping-cart"></i> 788 <span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span> 789 </button> 790 </div> 791 792 <div class="product-card__quantity--condenced product-card__quantity accessorie__quantity"> 793 <input id="Quantity_@accessoriesProduct.Id" class="product-card__quantity-input pointer-events js-quantity-input" name="Quantity@accessoriesProduct.Id" data-id="@accessoriesProduct.Id" type="number" min="1" max="@accessoriesProduct.Stock" value="1"> 794 <span class="product-card__quantity-add js-product-quantity-add" data-icon-nz="chevron-up"></span> 795 <span class="product-card__quantity-subtract js-product-quantity-subtract" data-icon-nz="chevron-down"></span> 796 </div> 797 798 </div> 799 </div> 800 } 801 else 802 { 803 804 <div class="grid__col-12 grid__col-sm-3 accessorie__controls"> 805 <div class="accessorie__controls-inner"> 806 <div class="accessorie__button-container d-inline-block"> 807 <button type="button" id="CartButton_@accessoriesProduct.Id" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" name="submit" data-target=".js-target"> 808 <span class="u-hidden-xs u-hidden-xxs"> @Translate("CallForPrice")</span> 809 </button> 810 </div> 811 </div> 812 </div> 813 } 814 } 815 } 816 } 817 else 818 { 819 <div class="grid__col-12 grid__col-sm-6 align-items-center align-items-lg-end"> 820 <div class="grid__cell"> 821 <div class="grid__col-12 pb-0"> 822 <h5>@Translate("LoginText")</h5> 823 </div> 824 <div class="grid__col-12 pb-0"> 825 <label for="SignInModalTrigger" class="btn btn--primary u-no-margin sign-in-modal-trigger-button dw-mod" onclick="setTimeout(function() { document.getElementById('LoginUsername').focus() }, 10)">@Translate("Sign in")</label> 826 </div> 827 </div> 828 </div> 829 } 830 </div> 831 </div> 832 } 833 } 834 <div class="grid__col--bleed-y mb-6"> 835 <a class="btn btn-teritary btn--load-more js-load-more-trigger dw-mod">@Translate("Load more")</a> 836 </div> 837 </form> 838 </div> 839 </div> 840 </div> 841 </section> 842 843 @if (GetLoop("ProductRelatedGroups").Any()) 844 { 845 <section class="related-products"> 846 <div class="grid related-products__inner-container"> 847 848 <div class="grid__col-xs-12 related-products__headline-container"> 849 <h2 class="related-products__headline h2 section-title section-title--condensed">@Translate("Related products")</h2> 850 </div> 851 852 <div class="grid__col-12 grid__col-md-10 grid__col--bleed m-auto"> 853 <div class="grid"> 854 855 @foreach (LoopItem relatedGroup in GetLoop("ProductRelatedGroups")) 856 { 857 foreach (LoopItem related in relatedGroup.GetLoop("RelatedProducts")) 858 { 859 Dynamicweb.Ecommerce.Products.Product currentRelatedProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(related.GetString("Ecom:Product.ID"), related.GetString("Ecom:Product.VariantID"), related.GetString("Ecom:Product.LanguageID")); 860 var relatedProductImagePathValue = Dynamicweb.Ecommerce.Services.Products.GetProductFieldValue(currentRelatedProduct, "ImagePath"); 861 string imgUrl = "/Files/Images/missing_image.jpg"; 862 string relatedProductImagePath = !string.IsNullOrWhiteSpace(relatedProductImagePathValue.ToString()) ? "/Files/Images/Ecom/LHI_Products/Images/" + relatedProductImagePathValue + ".jpg" : ""; 863 string relatedProductImage = !string.IsNullOrWhiteSpace(relatedProductImagePath) ? relatedProductImagePath : related.GetString("Ecom:Product.ImageLarge.Default.Clean"); 864 865 if (!string.IsNullOrWhiteSpace(relatedProductImage)) 866 { 867 imgUrl = relatedProductImage; 868 } 869 870 string name = related.GetString("Ecom:Product.Name"); 871 string number = related.GetString("Ecom:Product.Number"); 872 string price = related.GetString("Ecom:Product.Price"); 873 string groupId = related.GetString("Ecom:Product.PrimaryGroupID"); 874 string id = related.GetString("Ecom:Product.ID"); 875 var stock = related.GetInteger("Ecom:Product.Stock"); 876 string stockText = related.GetString("Ecom:Product:Stock.Text"); 877 878 <div class="grid__col-12 grid__col-sm-6 grid__col-lg-3"> 879 <div class="related-products__product related-product"> 880 <a href="@related.GetString("Ecom:Product.Link.Clean")"> 881 <div class="stickers-container dw-mod"> 882 883 884 885 @if (Converter.ToBoolean(Pageview.Area.Item["EnableSaleTags"])) 886 { 887 string contentType = Pageview.Area.Item["EcommerceSaleTagContentType"].ToString(); 888 string text = ""; 889 var currency = Dynamicweb.Ecommerce.Services.Currencies.GetDefaultCurrency(); 890 891 892 switch (contentType) 893 { 894 case "Name": 895 foreach (LoopItem relatedDiscounts in GetLoop("ProductDiscounts")) 896 { 897 text = relatedDiscounts.GetString("Ecom:Product.Discount.Name"); 898 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 899 } 900 break; 901 case "Amount": 902 if (GetLoop("ProductDiscounts").Count > 0) 903 { 904 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, GetDouble("Ecom:Product.Discount.Price.Price") - GetDouble("Ecom:Product.Price.Price")); 905 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 906 } 907 break; 908 case "Percents": 909 double percents = 0; 910 if (related.GetLoop("ProductDiscounts").Count > 0) 911 { 912 foreach (LoopItem discount in related.GetLoop("ProductDiscounts")) 913 { 914 if (discount.GetDouble("Ecom:Product.Discount.ProductQuantity") == 1) 915 { 916 percents = discount.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 917 } 918 } 919 if (percents > 0) 920 { 921 text = Math.Round(percents, 0) + "%"; 922 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 923 } 924 925 926 } 927 break; 928 case "Amount and percents": 929 double amount = 0; 930 double percent = 0; 931 foreach (LoopItem relatedDiscounts in GetLoop("ProductDiscounts")) 932 { 933 if (relatedDiscounts.GetString("Ecom:Product.Discount.Type") == "PERCENT") 934 { 935 percent += relatedDiscounts.GetDouble("Ecom:Product.Discount.PercentWithoutVAT"); 936 } 937 else if (relatedDiscounts.GetString("Ecom:Product.Discount.Type") == "AMOUNT") 938 { 939 amount += relatedDiscounts.GetDouble("Ecom:Product.Discount.AmountWithVAT"); 940 } 941 } 942 if (percent > 0) 943 { 944 text = percent + "%"; 945 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 946 } 947 if (amount > 0) 948 { 949 text = Dynamicweb.Ecommerce.Services.Currencies.Format(currency, amount); 950 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 951 } 952 break; 953 default: 954 if (GetLoop("ProductDiscounts").Count > 0) 955 { 956 text = Translate("Sale!"); 957 <div class="stickers-container__tag stickers-container__tag--sale dw-mod">@text</div> 958 } 959 break; 960 } 961 962 963 if (Converter.ToBoolean(Pageview.Area.Item["NewStickersEnable"]) && GetDate("Ecom:Product.Created").AddDays(Converter.ToDouble(Pageview.Area.Item["NewStickersExpiration"])) > DateTime.Now) 964 { 965 <div class="stickers-container__tag stickers-container__tag--new dw-mod">@Translate("New!")</div> 966 } 967 968 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Field.CustomSticker.Value"))) 969 { 970 <div class="stickers-container__tag stickers-container__tag--custom dw-mod">@GetString("Ecom:Product:Field.CustomSticker.Value")</div> 971 } 972 973 } 974 975 976 </div> 977 <img class="related-product__image b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=350&amp;height=350&amp;crop=5&amp;Compression=75&amp;DoNotUpscale=true&amp;image=@imgUrl" alt="@name" /> 978 <h4 class="related-product__name">@name</h4> 979 <div class="related-product__number">@Translate("product number") @number</div> 980 981 <div class="product-list-item__stock"> 982 <div class="stock-icon ml-0 @(stock > 0 ? "stock-icon--in" : "stock-icon--not")"></div> 983 <span>@stockText</span> 984 </div> 985 986 <span class="product-card__quantity-alert js-product-quantity-error-@id ">@Translate("Max stock level is reached")</span> 987 </a> 988 989 @if (!onlyPreview) 990 { 991 string priceWithDiscount = related.GetString("Ecom:Product.Discount.Price.Price"); 992 string currencySymbol = related.GetString("Ecom:Product.Currency.Symbol"); 993 string priceWithOutDiscount = related.GetString("Ecom:Product.Price.Price"); 994 bool productHasDiscount = GetBoolean("Ecom:Product.HaveDiscount"); 995 996 <div class="related-product__button-container d-inline-block"> 997 @if (priceWithDiscount != "0,00" || priceWithOutDiscount != "0,00") 998 { 999 if (GetString("Ecom:Product.Discount.TotalAmount") != "DKK 0,00") 1000 { 1001 <div class="related-product__price withdiscount">@currencySymbol @priceWithDiscount</div> 1002 } 1003 1004 else 1005 { 1006 <div class="related-product__price withoutdiscount">@priceWithOutDiscount</div> 1007 } 1008 <div class="related-product__controls"> 1009 <div class="product-card__quantity--condenced product-card__quantity related-product__quantity"> 1010 <input id="Quantity_@id" class="product-card__quantity-input pointer-events js-quantity-input" name="Quantity@id" data-id="@id" type="number" min="1" max="@stock" value="1"> 1011 <span class="product-card__quantity-add js-product-quantity-add" data-icon-nz="chevron-up"></span> 1012 <span class="product-card__quantity-subtract js-product-quantity-subtract" data-icon-nz="chevron-down"></span> 1013 </div> 1014 <button type="button" id="CartButton_@id" class="btn btn--primary related-product__cart" name="submit" onclick="Cart.AddToCart(event, '@id', document.getElementById('Quantity_@id').value, 'Unit_@id', 'Variant_@id');"> 1015 <i class="fa fa-shopping-cart"></i> 1016 <span class="u-hidden-xs u-hidden-xxs"> @Translate("Add to cart")</span> 1017 </button> 1018 </div> 1019 } 1020 else 1021 { 1022 <button type="button" id="CartButton_@id" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" name="submit" data-target=".js-target"> 1023 <span class="u-hidden-xs u-hidden-xxs"> @Translate("CallForPrice")</span> 1024 </button> 1025 } 1026 </div> 1027 1028 1029 } 1030 else 1031 { 1032 <div class="related-product__login-label">@Translate("LoginText")</div> 1033 <label for="SignInModalTrigger" class="btn btn--primary u-no-margin sign-in-modal-trigger-button dw-mod related-product__login" onclick="setTimeout(function () { document.getElementById('LoginUsername').focus() }, 10)">@Translate("Sign in")</label> 1034 } 1035 1036 1037 </div> 1038 </div> 1039 1040 1041 1042 1043 } 1044 1045 } 1046 1047 </div> 1048 </div> 1049 </div> 1050 </section> 1051 1052 1053 1054 } 1055 </div> 1056 1057 @* 1058 @if(GetLoop("eCom:Related.CustomersWhoSawThisAlsoSaw").Any()) 1059 { 1060 foreach (LoopItem item in GetLoop("eCom:Related.CustomersWhoSawThisAlsoSaw")) 1061 { 1062 relatedProductsFeed += item.GetString("Ecom:Product.ID"); 1063 relatedProductsFeed += ""; 1064 } 1065 1066 <div class="grid"> 1067 <div class="grid__col-12"> 1068 <div class="bg-gray bg-gray-full-width"> 1069 <h2 class="h1 section-title section-title--condensed">@Translate("ecom-related-products-3", "Related products")</h2> 1070 <div class="js-handlebars-root" id="ProductList_@productId" data-template="ProductContainer" data-pre-render-template="ProductPreRenderContainer" data-json-feed="@relatedProductsFeed" data-preloader="overlay"></div> 1071 </div> 1072 </div> 1073 </div> 1074 } 1075 *@ 1076 1077 @helper ProductPropertiesMainArea() 1078 { 1079 if (GetLoop("CustomFieldValues").Count > 0) 1080 { 1081 var visibleCount = 0; 1082 1083 <div class="specs-list specs-list--5"> 1084 <dl class="table table--clean table--compact product-page__specs-list"> 1085 @foreach (LoopItem customField in GetLoop("CustomFieldValues").Where(customField => customField.GetString("Product.CustomField.System") != "description").Where(customField => customField.GetString("Product.CustomField.System") != "LongDescription").Where(customField => customField.GetString("Product.CustomField.System") != "ShortDescription")) 1086 { 1087 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 1088 1089 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 1090 { 1091 fieldValue = ""; 1092 int count = 0; 1093 1094 foreach (LoopItem customFieldOptions in customField.GetLoop("Product.CustomField.Options").Where(customFieldOptions => !string.IsNullOrWhiteSpace(customFieldOptions.GetString("Product.CustomField.Option.Name")))) 1095 { 1096 if (customFieldOptions.GetBoolean("Product.CustomField.Option.IsSelected")) 1097 { 1098 if (count != 0) 1099 { 1100 fieldValue += ", "; 1101 } 1102 1103 fieldValue += customFieldOptions.GetString("Product.CustomField.Option.Name"); 1104 count++; 1105 } 1106 } 1107 } 1108 1109 if (fieldValue == "False") 1110 { 1111 fieldValue = Translate("No"); 1112 } 1113 1114 if (fieldValue == "True") 1115 { 1116 fieldValue = Translate("Yes"); 1117 } 1118 1119 1120 if (!String.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) 1121 && !String.IsNullOrWhiteSpace(fieldValue) 1122 && customField.GetString("Product.CustomField.Name") != "Custom sticker" 1123 && customField.GetString("Product.CustomField.Name").Contains("Produkt tekst") == true) 1124 { 1125 if (!String.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1126 { 1127 visibleCount++; 1128 <dd class="product-page__specs-value"><a href="@customField.GetString("Document.FullPath")" download title="@Translate("Download")" class="product__document"><span property="identifier">@getIconForFile(fieldValue) @Path.GetFileName(fieldValue)</span></a></dd> 1129 } 1130 else 1131 { 1132 visibleCount++; 1133 <dd class="product-page__specs-value"><span property="identifier">@fieldValue</span></dd> 1134 } 1135 } 1136 } 1137 </dl> 1138 1139 @if (visibleCount > 5) 1140 { 1141 <div class="js-load-more-specs specs-list__trigger"> 1142 <span class="specs-list__load-more">@Translate("Show more")</span> 1143 <span class="specs-list__load-less">@Translate("Show less")</span> 1144 </div> 1145 } 1146 1147 </div> 1148 } 1149 } 1150 @helper ProductProperties() 1151 { 1152 if (GetLoop("CustomFieldValues").Count > 0) 1153 { 1154 var visibleCount = 0; 1155 1156 <div class="specs-list specs-list--10"> 1157 <dl class="table table--clean table--compact product-page__specs-list"> 1158 @foreach (LoopItem customField in GetLoop("CustomFieldValues").Where(customField => customField.GetString("Product.CustomField.System") != "description").Where(customField => customField.GetString("Product.CustomField.System") != "LongDescription").Where(customField => customField.GetString("Product.CustomField.System") != "ShortDescription")) 1159 { 1160 string fieldValue = customField.GetString("Product.CustomField.Value.Clean"); 1161 1162 if (customField.GetLoop("Product.CustomField.Options").Count > 0) 1163 { 1164 fieldValue = ""; 1165 int count = 0; 1166 1167 foreach (LoopItem customFieldOptions in customField.GetLoop("Product.CustomField.Options").Where(customFieldOptions => !string.IsNullOrWhiteSpace(customFieldOptions.GetString("Product.CustomField.Option.Name")))) 1168 { 1169 if (customFieldOptions.GetBoolean("Product.CustomField.Option.IsSelected")) 1170 { 1171 if (count != 0) 1172 { 1173 fieldValue += ", "; 1174 } 1175 1176 fieldValue += customFieldOptions.GetString("Product.CustomField.Option.Name"); 1177 count++; 1178 } 1179 } 1180 } 1181 if (fieldValue == "False") 1182 { 1183 fieldValue = Translate("No"); 1184 } 1185 1186 if (fieldValue == "True") 1187 { 1188 fieldValue = Translate("Yes"); 1189 } 1190 1191 if (!String.IsNullOrEmpty(customField.GetString("Product.CustomField.Name")) 1192 && !String.IsNullOrWhiteSpace(fieldValue) 1193 && customField.GetString("Product.CustomField.Name") != "Custom sticker" 1194 && !customField.GetString("Product.CustomField.Name").Contains("Produktions ansvarlig") 1195 && !customField.GetString("Product.CustomField.Name").Contains("Video") 1196 && !customField.GetString("Product.CustomField.Name").Contains("PDF") 1197 && !customField.GetString("Product.CustomField.Name").Contains("Lokation") 1198 && !customField.GetString("Product.CustomField.Name").Contains("Status") 1199 && !customField.GetString("Product.CustomField.Name").Contains("Produktgr. (CO)") 1200 && !customField.GetString("Product.CustomField.Name").Contains("Produktprisgr. 1 (rabatgruppe)") 1201 && !customField.GetString("Product.CustomField.Name").Contains("Prisliste") 1202 && !customField.GetString("Product.CustomField.Name").Contains("Godkendelse") 1203 && !customField.GetString("Product.CustomField.Name").Contains("Salgsstatistik") 1204 && !customField.GetString("Product.CustomField.Name").Contains("ABC") 1205 && !customField.GetString("Product.CustomField.Name").Contains("Billedefilnr (LFR)") 1206 && !customField.GetString("Product.CustomField.Name").Contains("Rabat gruppe 2") 1207 && !customField.GetString("Product.CustomField.Name").Contains("Visma changed by user") 1208 && !customField.GetString("Product.CustomField.Name").Contains("Visma changed date") 1209 && customField.GetString("Product.CustomField.Value") != "0" 1210 && customField.GetString("Product.CustomField.Value") != "" 1211 && customField.GetString("Product.CustomField.Name").Contains("Produkt tekst") != true) 1212 { 1213 <dt class="product-page__specs-display" width="160">@Translate(customField.GetString("Product.CustomField.Name")): </dt> 1214 if (!String.IsNullOrEmpty(customField.GetString("Document.FullPath"))) 1215 { 1216 visibleCount++; 1217 <dd class="text-right product-page__specs-value"><a href="@customField.GetString("Document.FullPath")" download title="@Translate("Download")" class="product__document"><span property="identifier">@getIconForFile(fieldValue) @Path.GetFileName(fieldValue)</span></a></dd> 1218 } 1219 else 1220 { 1221 visibleCount++; 1222 <dd class="text-right product-page__specs-value"><span property="identifier">@fieldValue</span></dd> 1223 } 1224 } 1225 } 1226 </dl> 1227 1228 @if (visibleCount > 10) 1229 { 1230 <div class="js-load-more-specs specs-list__trigger"> 1231 <span class="specs-list__load-more">@Translate("Show more")</span> 1232 <span class="specs-list__load-less">@Translate("Show less")</span> 1233 </div> 1234 } 1235 </div> 1236 } 1237 1238 if (GetLoop("ProductCategories").Count > 0) 1239 { 1240 <dl class="product-page__specs-list"> 1241 @foreach (LoopItem categoryGroup in GetLoop("ProductCategories")) 1242 { 1243 int fieldsCount = 0; 1244 foreach (LoopItem categoryField in categoryGroup.GetLoop("ProductCategoryFields")) 1245 { 1246 if (!String.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Value"))) 1247 { 1248 fieldsCount++; 1249 } 1250 } 1251 if (fieldsCount > 0) 1252 { 1253 <dd class="product-page__specs-display">@categoryGroup.GetString("Ecom:Product.Category.Name")</dd> 1254 1255 foreach (LoopItem categoryField in categoryGroup.GetLoop("ProductCategoryFields")) 1256 { 1257 string fieldValue = categoryField.GetString("Ecom:Product.CategoryField.Value"); 1258 1259 if (fieldValue == "False") 1260 { 1261 fieldValue = Translate("No"); 1262 } 1263 1264 if (fieldValue == "True") 1265 { 1266 fieldValue = Translate("Yes"); 1267 } 1268 1269 if (!String.IsNullOrEmpty(categoryField.GetString("Ecom:Product.CategoryField.Label")) && !String.IsNullOrEmpty(fieldValue)) 1270 { 1271 <dt class="product-page__specs-display">@categoryField.GetString("Ecom:Product.CategoryField.Label"):</dt> 1272 <dd class="text-right product-page__specs-value"><span property="identifier">@fieldValue</span></dd> 1273 } 1274 } 1275 } 1276 } 1277 </dl> 1278 } 1279 } 1280 1281 <script id="PricesAndActionsTemplate" type="text/x-template"> 1282 {{#.}} 1283 1284 @if (!onlyPreview) 1285 { 1286 if (cfp == false) 1287 { 1288 if (GetString("Ecom:Product.Discount.TotalAmount") != "DKK 0,00") 1289 { 1290 <small class="text-gray font-weight-light">@Translate("NettoPrice")</small> 1291 <div class="text-gray font-weight-light product__price--discount {{onSale}}">{{#Discount}}{{#if @@first}}{{this.discountPrice}}{{/if}}{{/Discount}}</div> 1292 <br /> 1293 <small class="text-gray font-weight-light">@Translate("ProductDiscount")</small> 1294 <div class="text-gray font-weight-light product__price--discount {{onSale}}">{{#Discount}}{{#if @@first}}{{this.discountCurrency}} {{this.subtractPriceWithoutDecimals}}{{/if}}{{/Discount}}</div> 1295 <br /> 1296 <small class="text-gray font-weight-light">@Translate("PriceWithDiscount")</small> 1297 1298 } 1299 1300 else 1301 { 1302 <small class="text-gray font-weight-light">@Translate("PriceWithoutDiscount")</small> 1303 1304 } 1305 1306 if (GetLoop("ProductDiscounts").Any()) 1307 { 1308 <div class="h1 my-3 text-gray font-weight-light">{{#each Discount}}{{#if @@first}}{{this.unitPrice}}{{/if}}{{/each}}</div> 1309 } 1310 else 1311 { 1312 <div class="h1 my-3 text-gray font-weight-light">{{#each Discount}}{{#if @@first}}{{this.discountPrice}}{{/if}}{{/each}}</div> 1313 } 1314 1315 1316 1317 } 1318 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.Text")) || !String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText"))) 1319 { 1320 if (GetLoop("Product.Prices").Count >= 1) 1321 { 1322 1323 var priceLoop = GetLoop("Product.Prices"); 1324 var excludedIds = "1"; 1325 var priceQuantity = priceLoop.Where(i => !excludedIds.Contains(i.GetString("Ecom:Product.Prices.Quantity"))); 1326 1327 if (GetLoop("Product.Prices").Count > 1 && priceQuantity.Any()) 1328 { 1329 1330 1331 <div class="js-popup"> 1332 <a class="js-popup-trigger">@Translate("DiscountText")</a> 1333 <div class="js-popup-modal popup_productview"> 1334 <div class="js-popout-close nz-icon icon-nz-close-circled"></div> 1335 <ul class="grid__col-12 pt-5 p-0 d-flex flex-row flex-wrap"> 1336 @* FOREACH DISCOUNT LOOP FROM JSON FEED *@ 1337 {{#each Discount}} 1338 {{#unless @@first}} 1339 <li class="grid__col-lg-6 p-0 mb-0 grid__col-12 align-items-center align-items-xl-start">@Translate("UnitPriceText") {{this.discountQuantity}} @Translate("UnitPriceTextStk")</li> 1340 <li class="grid__col-lg-6 p-0 pb-3 grid__col-12 align-items-center align-items-xl-end">{{this.discountPrice}} {{this.discountCurrency}}</li> 1341 {{/unless}} 1342 {{/each}} 1343 1344 </ul> 1345 </div> 1346 </div> 1347 } 1348 } 1349 <br> 1350 1351 if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.Text")) || !String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText"))) 1352 { 1353 string stockIcon = GetInteger("Ecom:Product.Stock") > 0 ? "product__stock-icon--in" : "product__stock-icon--not"; 1354 1355 if (cfp == false) 1356 { 1357 <table class="table table--clean delivery-and-stock-info dw-mod"> 1358 <tr> 1359 <td class="u-no-padding"> 1360 <div class="stock-icon ml-0 @stockIcon"></div> 1361 <span class="font-weight-bold">@GetString("Ecom:Product:Stock.Text")</span> 1362 </td> 1363 </tr> 1364 <tr> 1365 @* 1366 @if (!String.IsNullOrEmpty(GetString("Ecom:Product:Stock.DeliveryText"))) 1367 { 1368 <td class="u-no-padding">@Translate("Shipping") @GetString("Ecom:Product:Stock.DeliveryText") @GetString("Ecom:Product:Stock.DeliveryUnit")</td> 1369 } 1370 *@ 1371 </tr> 1372 </table> 1373 } 1374 } 1375 1376 <div class="buttons-collection product__price-actions__actions dw-mod d-inline-block d-lg-flex mt-5 w-100"> 1377 1378 @if (GetBoolean("Ecom:Product:Field.CFP")) 1379 { 1380 <div class="cfp-btn-container pt-4 pt-lg-0"> 1381 <button type="button" id="CartButton_{{id}}" class="btn btn-primary dw-mod js-scroll-btn d-inline-block px-5" name="submit" data-target=".js-target">@Translate("CallForPrice")</button> 1382 </div> 1383 } 1384 1385 else 1386 { 1387 @* Product quantity *@ 1388 <div class="product-card__quantity product-card__quantity--condenced"> 1389 <input id="Quantity_{{id}}" class="product-card__quantity-input pointer-events js-quantity-input" data-id="{{id}}" name="Quantity" type="number" min="1" max="@stockAmount" value="1"> 1390 <span class="product-card__quantity-add js-product-quantity-add" data-icon-nz="chevron-up"></span> 1391 <span class="product-card__quantity-subtract js-product-quantity-subtract" data-icon-nz="chevron-down"></span> 1392 </div> 1393 <div class="product-btn-buy-container pt-4 pt-lg-0 pl-lg-3"> 1394 <button type="button" id="CartButton_{{id}}" class="btn btn-primary dw-mod d-inline-block px-5" name="submit" onclick="Cart.AddToCart(event, '{{productId}}', document.getElementById('Quantity_{{id}}').value, 'Unit_{{id}}', 'Variant_{{productId}}');">@Translate("Add to cart")</button> 1395 </div> 1396 } 1397 1398 @if (Dynamicweb.Core.Converter.ToBoolean(GetGlobalValue("Global:Extranet.UserName"))) 1399 { 1400 string favoriteId = "Favorite" + GetString("Ecom:Product.ID"); 1401 1402 <div id="@favoriteId" class="favorites fav-product-container favorites--md d-inline-block dw-mod p-0 pl-lg-3"> 1403 <label for="FavoriteTrigger" class="btn mb-0 btn-secondary"><span class="pr-2 product__add-to-favorites"></span><small class="x-small">@Translate("Add to list")</small></label> 1404 <input type="checkbox" id="FavoriteTrigger" class="dropdown-trigger"> 1405 <div class="dropdown"> 1406 <div class="dropdown__content dropdown__content--show-left dropdown__content--padding u-w220px dw-mod"> 1407 @if (GetLoop("CustomerCenter.ListTypes").Any()) 1408 { 1409 <ul class="list list--clean dw-mod"> 1410 @foreach (LoopItem listType in GetLoop("CustomerCenter.ListTypes")) 1411 { 1412 foreach (LoopItem list in listType.GetLoop("CustomerCenter.ProductLists")) 1413 { 1414 <li> 1415 @{string favLinkType = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? list.GetString("Ecom:Product.RemoveFromThisList") : list.GetString("Ecom:Product.AddToThisListAction");} 1416 @{string isInListIcon = list.GetString("Ecom:Product.List.IsProductInThisList") == "True" ? "fa fa-star" : "fa fa-star-o";} 1417 <a href="@favLinkType" class="list__link dw-mod"><i class="@isInListIcon"></i> @list.GetValue("Ecom:CustomerCenter.List.Name")</a> 1418 </li> 1419 } 1420 } 1421 </ul> 1422 } 1423 1424 else 1425 { 1426 <p>@Translate("CreateFavoritList")</p><a class="btn-sm btn-primary d-block text-center" href="@favoritPage">@Translate("CreateFavoritListButton")</a> 1427 } 1428 1429 </div> 1430 <label class="dropdown-trigger-off" for="FavoriteTrigger"></label> 1431 </div> 1432 </div> 1433 } 1434 1435 1436 </div> 1437 1438 <span class="product-card__quantity-alert js-product-quantity-error-{{id}}">@Translate("Max stock level is reached")</span> 1439 } 1440 } 1441 1442 else 1443 { 1444 <button type="button" id="CartButton_{{id}}" class="u-hidden"></button> 1445 } 1446 {{/.}} 1447 </script> 1448 1449 <script id="Units" type="text/x-template"> 1450 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '/Default.aspx?ID=@feedId&UnitID={{value}}')">{{name}}</div> 1451 </script> 1452 1453 1454 @* Script templates for related products *@ 1455 <script id="ProductPreRenderContainer" type="text/x-template"> 1456 <div class="u-h600px u-full-width"> 1457 <div class="grid"> 1458 <div class="grid__col-12"> 1459 <div class="pre-render-element pre-render-element--md"></div> 1460 </div> 1461 </div> 1462 </div> 1463 </script> 1464 1465 <script id="ProductContainer" type="text/x-template"> 1466 {{#.}} 1467 <div class="u-min-h400px u-full-width"> 1468 <div class="grid"> 1469 <div class="grid__col-45px grid__col--bleed-x"> 1470 <div class="grid__cell grid__cell--align-middle-left"> 1471 <button class="btn btn--condensed btn--clean {{prevdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{prevPage}}')" {{prevdisabled}}><i class="fa fa-chevron-left fa-2x"></i></button> 1472 </div> 1473 </div> 1474 <div class="grid__col-auto grid__col--bleed-x"> 1475 <div id="ProductsContainer" class="grid product-list dw-mod"> 1476 {{#ProductsContainer}} 1477 <div id="Product{{productId}}" class="grid__col-@relatedProductsColumnWidth product-list__list-item dw-mod"> 1478 <div class="product-list__inner"> 1479 {{#Product}} 1480 <div class="grid__cell product-list__grid-item__image dw-mod {{noImage}}"> 1481 <div class="stickers-container dw-mod"> 1482 {{#Stickers}} 1483 {{>Sticker}} 1484 {{/Stickers}} 1485 </div> 1486 <a href="{{link}}" onclick="Scroll.SavePosition(event)"><img class="grid__cell-img grid__cell-img--centered b-lazy" src="/Files/Images/placeholder.gif" data-src="/Admin/Public/GetImage.ashx?width=300&amp;height=300&amp;crop=5&amp;Compression=75&amp;image={{image}}" alt="{{name}}" /></a> 1487 </div> 1488 1489 <div class="grid__cell product-list__grid-item__price-info {{shortGridInfo}} dw-mod"> 1490 <a href="{{link}}" onclick="Scroll.SavePosition(event)" title="{{name}}"><h6 class="u-condensed-text">{{name}}</h6></a> 1491 <div class="item-number dw-mod">{{number}}</div> 1492 1493 @if (!onlyPreview && cfp == true) 1494 { 1495 <div class="price dw-mod">{{price}}</div> 1496 <div class="before-price {{onSale}} dw-mod">{{discount}}</div> 1497 } 1498 </div> 1499 1500 <div class="product-list__grid-item__footer dw-mod"> 1501 <div class="u-ta-center"> 1502 1503 @if (!onlyPreview && cfp == true) 1504 { 1505 <a href="{{link}}" id="CartButton_{{id}}" class="btn btn--secondary text-uppercase u-no-margin dw-mod">@Translate("View")</a> 1506 } 1507 else 1508 { 1509 <h5 class="mb-2">@Translate("LoginText", "Login")</h5> 1510 <label for="SignInModalTrigger" class="btn btn--primary u-no-margin sign-in-modal-trigger-button dw-mod" onclick="setTimeout(function () { document.getElementById('LoginUsername').focus() }, 10)">@Translate("Sign in")</label> 1511 } 1512 </div> 1513 </div> 1514 {{/Product}} 1515 </div> 1516 </div> 1517 {{/ProductsContainer}} 1518 </div> 1519 </div> 1520 1521 <div class="grid__col-45px grid__col--bleed-x"> 1522 <div class="grid__cell grid__cell--align-middle-right"> 1523 <button class="btn btn--condensed btn--clean {{nextdisabled}} dw-mod" onclick="HandlebarsBolt.UpdateContent('ProductList_{{groupName}}', '{{nextPage}}')" {{nextdisabled}}><i class="fa fa-chevron-right fa-2x"></i></button> 1524 </div> 1525 </div> 1526 1527 </div> 1528 </div> 1529 {{/.}} 1530 </script> 1531 1532 <script id="Sticker" type="text/x-template"> 1533 <div class="stickers-container__tag {{className}} dw-mod">{{text}}</div> 1534 </script> 1535 1536 @* Units templates *@ 1537 1538 <script id="UnitOption" type="text/x-template"> 1539 <div class="dropdown__item dw-mod" onclick="HandlebarsBolt.UpdateContent('PriceAndActions', '{{link}}&feed=true&UnitID={{value}}&rid={{id}}')">{{name}}</div> 1540 </script> 1541 1542 1543 @*Variants data generation*@ 1544 1545 <script> 1546 document.addEventListener("DOMContentLoaded", function (event) { 1547 var variants = []; 1548 1549 document.getElementById("productGrid").addEventListener('contentLoaded', function (e) { 1550 if (e.srcElement.classList.contains("js-variants-wrap")) { 1551 Variants.SetVariantOptionStatesForProductList(e.srcElement); 1552 } 1553 }, false); 1554 1555 @foreach (LoopItem variantgroup in GetLoop("VariantGroups")) 1556 { 1557 <text>var optionsArray = [];</text> 1558 1559 foreach (LoopItem variantoption in variantgroup.GetLoop("VariantAvailableOptions")) 1560 { 1561 string variantSelection = variantoption.GetBoolean("Ecom:VariantOption.Selected") ? "checked" : ""; 1562 1563 <text> 1564 var option = new Variants.VariantOption("@uniqueId", "@GetString("Ecom:Product.ID")", "@variantoption.GetValue("Ecom:VariantOption.ID")", "@variantoption.GetString("Ecom:VariantOption.Name")", "@variantSelection", "", "@variantoption.GetString("Ecom:VariantOption.Color")", "@variantoption.GetString("Ecom:VariantOption.ImgSmall.Clean")"); 1565 optionsArray.push(option); 1566 </text> 1567 } 1568 1569 <text> 1570 var group = new Variants.VariantGroup("@GetString("Ecom:Product.ID")_@variantgroup.GetValue("Ecom:VariantGroup.ID")", "@variantgroup.GetValue("Ecom:VariantGroup.Name")", optionsArray); 1571 variants.push(group); 1572 </text> 1573 } 1574 1575 var combinations = []; 1576 @foreach (LoopItem variantcomb in GetLoop("VariantStockCombinations")) 1577 { 1578 <text> 1579 combinations.push(new Variants.CombinationItem("@variantcomb.GetValue("Ecom:VariantStockCombination.VariantID")")); 1580 </text> 1581 } 1582 1583 variants = variants.sort(function (a, b) { 1584 var firstVariantId = a.VariantOptions[0].variantId; 1585 for (var i = 0; i < combinations.length; i++) { 1586 var combinationIndex = combinations[i].id.indexOf(firstVariantId); 1587 if (combinationIndex != -1) { 1588 return combinationIndex; 1589 } 1590 } 1591 //should never happen 1592 return 0; 1593 }); 1594 1595 Variants.SetProductFeedId('@feedId'); 1596 Variants.SetProductUrl('/@GetString("Ecom:Product.VariantLinkGroup.Clean")'); 1597 1598 HandlebarsBolt.SetDataInCache(("Variants" + "@productId"), variants); 1599 HandlebarsBolt.SetDataInCache(("Combinations" + "@productId"), combinations); 1600 1601 document.getElementById("PriceAndActions").addEventListener('contentLoaded', function (e) { 1602 Variants.InitVariants(variants, combinations, "@productId", "@uniqueId"); 1603 }, false); 1604 1605 1606 Handlebars.registerHelper('compare', function (lvalue, operator, rvalue, options) { 1607 1608 var operators, result; 1609 1610 if (arguments.length < 3) { 1611 throw new Error("Handlerbars Helper 'compare' needs 2 parameters"); 1612 } 1613 1614 if (options === undefined) { 1615 options = rvalue; 1616 rvalue = operator; 1617 operator = "==="; 1618 } 1619 1620 operators = { 1621 '==': function (l, r) { return l == r; }, 1622 '===': function (l, r) { return l === r; }, 1623 '!=': function (l, r) { return l != r; }, 1624 '!==': function (l, r) { return l !== r; }, 1625 '<': function (l, r) { return l < r; }, 1626 '>': function (l, r) { return l > r; }, 1627 '<=': function (l, r) { return l <= r; }, 1628 '>=': function (l, r) { return l >= r; }, 1629 'typeof': function (l, r) { return typeof l == r; } 1630 }; 1631 1632 if (!operators[operator]) { 1633 throw new Error("Handlerbars Helper 'compare' doesn't know the operator " + operator); 1634 } 1635 1636 result = operators[operator](lvalue, rvalue); 1637 1638 if (result) { 1639 return options.fn(this); 1640 } else { 1641 return options.inverse(this); 1642 } 1643 1644 }); 1645 1646 1647 }); 1648 </script> 1649 1650 @functions { 1651 string getIconForFile(string fileName) 1652 { 1653 string ext = Path.GetExtension(fileName); 1654 string icon = ""; 1655 switch (ext.ToLower()) 1656 { 1657 case ".xls": 1658 case ".xlsx": 1659 icon = "fa-file-excel-o"; 1660 break; 1661 case ".ppt": 1662 case ".pptx": 1663 icon = "fa-file-powerpoint-o"; 1664 break; 1665 case ".doc": 1666 case ".docx": 1667 icon = "fa-file-word-o"; 1668 break; 1669 case ".jpg": 1670 case ".jpeg": 1671 case ".png": 1672 case ".gif": 1673 case ".pdf": 1674 return "<img class='product__document-icon b-lazy' src='/Files/Images/placeholder.gif' data-src='/Admin/Public/GetImage.ashx?crop=5&height=70&width=120&Compression=75&DoNotUpscale=true&image=" + fileName + "' />"; 1675 default: 1676 icon = "fa-file-o"; 1677 break; 1678 } 1679 return "<i class='fa " + icon + "'></i> "; 1680 } 1681 1682 public static string ToPascalCase(string str) 1683 { 1684 return CultureInfo.InvariantCulture.TextInfo 1685 .ToTitleCase(str.ToLowerInvariant()) 1686 .Replace("-", "") 1687 .Replace("_", "") 1688 .Replace(" ", ""); 1689 } 1690 } 1691 1692 <script type="application/ld+json"> 1693 { 1694 "@@context": "http://schema.org/", 1695 "@@type": "Product", 1696 "name": "@GetString("Ecom:Product.Name")", 1697 @if (!string.IsNullOrEmpty(GetString("Ecom:Product.ImageLarge.Default.Clean"))) 1698 { 1699 <text>"image": [ 1700 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=400&crop=0&Compression=75&DoNotUpscale=true&image=@productImage", 1701 "@siteURL/Admin/Public/GetImage.ashx?width=400&height=300&crop=0&Compression=75&DoNotUpscale=true&image=@productImage", 1702 "@siteURL/Admin/Public/GetImage.ashx?width=448&height=225&crop=0&Compression=75&DoNotUpscale=true&image=@productImage" 1703 ],</text> 1704 } 1705 "description": "@GetString("Ecom: Product.ShortDescription")", 1706 "mpn": "925872", 1707 @if (!string.IsNullOrEmpty(brand)) 1708 { 1709 <text>"brand": { 1710 "@@type": "Thing", 1711 "name": "@brand" 1712 },</text> 1713 } 1714 "offers": { 1715 "@@type": "Offer", 1716 "priceCurrency": "@GetString("Ecom:Product.Price.Currency.Code")", 1717 "price": "@GetString("Ecom:Product.Price.Price")", 1718 "availability": "@(GetInteger("Ecom:Product.Stock") > 0 ? "InStock" : "OutOfStock")" 1719 } 1720 } 1721 </script>

Tilmelding til kursus

Tilmeld dig et af vore kurser og få den nyeste viden inden for sikker håndtering af spildevand.

Kontakt os

Har du spørgsmål til vores produkter, løsninger eller services? Eller søger du hjælp til beregninger og dimensioneringer? Vi står klar til at hjælpe. Udfyld formularen herunder, og vi kontakter dig hurtigst muligt.