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