Vi sender din ordre om:
t: m: s
Close
  • Leveringstid 2-5 virkedager
  • Gratis frakt fra 500 kr.
  • Dansk håndverk siden 1956
Norsk Dansk English Deutsch Nederlands
Handlekurv Handlekurv
Scanpan
  • Panner
    Gå til Panner
    • Inspirasjon
      • Panner til alle formål
      • Panner til induksjon
      • Non-stick-panner
      • Panner i kobber
    • Kategorier
      • Stekepanner
      • Langpanner
      • Grillpanner
      • Traktørpanner
      • Wok
      • Spesialprodukter
    • Serier
      • NYHET! Pro SB+
      • NYHET! Urban
      • TechnIQ
      • CTX
      • Pro IQ
      • Classic
      • Classic Induction
      • Se alle serier
    • Da er det alltid grillvær!
      høye og spisse grillriller
  • Gryter
    Gå til Gryter
    • Inspirasjon
      • Gryter til alle formål
      • Gryter til induksjon
      • Gryter i stål
      • Kobbergryter
    • Kategorier
      • Gryter
      • Kasseroller
      • Grytesett
      • Spesialprodukter
      • Tilbehør til gryter
    • Serier
      • NYHET! Pro SB+
      • CTX
      • Pro IQ
      • Classic Induction
      • Impact
      • Se alle serier
    • Non-stick gryter
      geniale til grytebrød
  • Kniver
    Gå til Kniver
    • Inspirasjon
      • Kniver til alle formål
    • Kategorier
      • Kniver til kjøtt
      • Kniver til grønt
      • Kniver til brød
      • Knivsett
      • Knivsliping
      • Grillbestikk
      • Tilbehør
    • Serier
      • Classic
      • Maitre D
    • Knivmagnet
      i vakker eik
  • Tilbehør
    Gå til Tilbehør
    • Kategorier
      • Kjøkkenredskaper
      • Lokk
      • Rister og innsatser
      • Vedlikehold
      • Skjærebrett
    • Elegant morter
      i eik og støpejern
  • TO GO
    Gå til TO GO
    • Kategorier
      • Termoflaske
      • Termokrus
      • Termokopp
      • Presskande
      • Termoflaske Premium
      • Termo tumbler
      • Premium gavesett
    • Trendy termo
      for kaldt og varmt
  • Serier
    Gå til Serier
    • Oversikt
      • Se alle serier
      • NYHET! Pro SB+
      • NYHET! Urban
      • STS
      • Black Iron
    • Våre universer
      • Crafted by Chefs – kjøkkenutstyr Nytenkt
      • Classic – et univers av funksjonelt håndverk
      • Maitre D' – et univers av luksus og estetikk
    • Dansk siden 1956
      Stolt, dansk håndverk
  • SCANPAN Guiden
Error executing template "Designs/Scanpan/eCom/Product/product.cshtml"
System.InvalidOperationException: Sequence contains no elements
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at CompiledRazorTemplates.Dynamic.RazorEngine_e44cf973f6624e789ceae3117dc918cc.Execute() in E:\dynamicweb.net\Solutions\scanpan-live\Files\Templates\Designs\Scanpan\eCom\Product\product.cshtml:line 328
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @using System.Web 2 @using System.Drawing 3 @using Dynamicweb 4 @using Dynamicweb.Admin 5 @using Dynamicweb.Data 6 @inherits RazorTemplateBase<RazorTemplateModel<Template>> 7 @using Dynamicweb.Rendering 8 @using NoZebra.Util 9 @using Dynamicweb.Content; 10 @using Dynamicweb.Content.Items; 11 @using System.Text.RegularExpressions; 12 @* Note that this file will be inserted directly into another one by Dynamicweb IncludeFile 13 before evaluating the Razor code, so keep the syntax right *@ 14 15 @functions { 16 17 /** 18 * Custom date format from string input 19 * String needs to be in a date format, though 20 * @param {String} d 21 */ 22 string FormatDate(string d) { 23 string output = d; 24 // Language 25 string lang = GetGlobalValue("Global:Area.Lang"); 26 // Date format 27 string dateFormat = (lang == "da") ? "d. MMM. yyyy" : "MMM d yyyy"; 28 // Try parsing string as DateTime 29 DateTime dateValue; 30 if (DateTime.TryParse(d, out dateValue)) { 31 output = dateValue.ToString(dateFormat); 32 } 33 // Format date input 34 // Return formatted date 35 return output; 36 } 37 38 /** 39 * Format number form string input 40 * Returns a clean number to be used in sorting loops 41 * @param {String} s 42 */ 43 string FormatNumber(string s) { 44 Regex rgx = new Regex(@"[^0-9.,]"); // match everything but numbers, comma and period 45 // Replace all letters with whitespace 46 s = rgx.Replace(s, " "); 47 // Remove everything after the first space 48 // This takes care of values like "28 x 28 cm" and "20 l" 49 return s.Split(new[]{" "}, StringSplitOptions.None)[0]; 50 } 51 52 /** 53 * Custom number formatting from string input 54 * @param {String} s 55 */ 56 decimal NumberFromString(String s) { 57 decimal output = decimal.Parse("0"); // fallback 58 string inputFormatted = FormatNumber(s); // strip input of anything but numbers 59 // Check if item has a value in the field 60 if( !string.IsNullOrEmpty(inputFormatted) ) { 61 decimal parsed; 62 // Try parsing formatted input as a decimal 63 if (decimal.TryParse(inputFormatted, out parsed)) { 64 output = parsed; 65 } 66 } 67 return output; 68 } 69 70 /** 71 * Order product loop by size field 72 * @param {LoopItem} v 73 */ 74 decimal OrderProductsBySize(LoopItem v) { 75 return NumberFromString(v.GetString("Ecom:Product:Field.SIZ")); 76 } 77 78 /** 79 * Order product loop by volume field 80 * @param {LoopItem} v 81 */ 82 decimal OrderProductsByVolume(LoopItem v) { 83 return NumberFromString(v.GetString("Ecom:Product:Field.VOL")); 84 } 85 86 /** 87 * Check wether a product id exists in a list of ids 88 * @param {List<string>} list 89 * @param {String} productId 90 */ 91 bool HasProduct(List<string> list, string productId) { 92 string productIdFormatted = "p_" + productId; 93 return list.Any(x => x == productIdFormatted); 94 } 95 96 /** 97 * Check wether a blog post page has a product selected 98 * in its related products field 99 * @param {Dynamicweb.Content.Page} blogPostAsPage 100 * @param {String} productId 101 */ 102 bool BlogPostHasRelatedProduct(Page blogPostAsPage, string productId) { 103 // Get page item 104 Item blogItem = ItemManager.Storage.GetById("BlogPost", blogPostAsPage.ItemId.ToString()); 105 // Get products from blog post fields 106 List<string> blogProducts = blogItem["Products"].ToString() 107 .Split(',') 108 .ToList(); 109 // Test wether provided product number matches any in the field 110 return HasProduct(blogProducts, productId); 111 } 112 113 bool BlogPostIsRelated(List<LoopItem> currentPageCategories, List<LoopItem> compareCategories) { 114 115 foreach(var i in compareCategories) { 116 if(currentPageCategories.Any(x => (x.GetInteger("ItemPublisher:Item.Categories.Id") == i.GetInteger("ItemPublisher:Item.Categories.Id")))) { 117 return true; 118 } 119 } 120 121 // No match 122 return false; 123 } 124 125 string ConvertPriceToSouthAfricanFormat(string price, int areaId) 126 { 127 if (areaId == 28) 128 { 129 int place = price.LastIndexOf(','); 130 131 if (place == -1) 132 return price; 133 134 string result = price.Remove(place, 1).Insert(place, "."); 135 return result; 136 } 137 return price; 138 } 139 140 } 141 142 @{ 143 string productNumber = GetString("Ecom:Product.Number"); 144 string productColor = GetString("Ecom:Product:Field.COL"); 145 string productSize = GetString("Ecom:Product:Field.SIZ"); 146 string productBottomDiameter = GetString("Ecom:Product:Field.ItemBaseDiameter"); 147 string productVolume = GetString("Ecom:Product:Field.VOL"); 148 string productWeight = GetString("Ecom:Product.Weight"); 149 150 // Getting list of products from product picker 151 List<string> selectedProducts = Pageview.Area.Item["ProductDetailCategories"] 152 .ToString() 153 .Split(',') 154 .ToList(); 155 // Formatting product id to match that of the list items above 156 string productIdFormatted = "p_" + GetString("Ecom:Product.ID"); 157 // Check if current product is in the list 158 bool hasDiameter = selectedProducts.IndexOf(productIdFormatted) == -1; 159 160 Dictionary<string, Dictionary<string, string>> details = new Dictionary<string, Dictionary<string, string>>() { 161 { 162 "weight", new Dictionary<string, string>(){ 163 { "text", "Weight" }, 164 { "description", null }, 165 { "value", productWeight + " kg" }, 166 { "is-empty", string.IsNullOrEmpty(productWeight).ToString() } 167 } 168 }, 169 { 170 "product-number", new Dictionary<string, string>(){ 171 { "text", "Product number" }, 172 { "description", null }, 173 { "value", productNumber }, 174 { "is-empty", "False" } 175 } 176 } 177 }; 178 179 /* Is pot or pan */ 180 if(hasDiameter) { 181 182 /** 183 * Creating new dictionary to merge 184 * This way we can prepend the new values to the existing dictionary 185 */ 186 Dictionary<string, Dictionary<string, string>> addValues = new Dictionary<string, Dictionary<string, string>>() { 187 { 188 "top-diameter", new Dictionary<string, string>(){ 189 { "text", "Top diameter" }, 190 { "description", Pageview.Area.Item["ProductDetailDiameterTopDescription"].ToString() }, 191 { "value", productSize }, 192 { "is-empty", string.IsNullOrEmpty(productSize).ToString() } 193 } 194 }, 195 { 196 /* TBD: This is not currently in eCom */ 197 "bottom-diameter", new Dictionary<string, string>(){ 198 { "text", "Bottom diameter" }, 199 { "description", Pageview.Area.Item["ProductDetailDiameterBottomDescription"].ToString() }, 200 { "value", productBottomDiameter }, 201 { "is-empty", string.IsNullOrEmpty(productBottomDiameter).ToString() } 202 } 203 } 204 }; 205 206 /* Merge dictionaries */ 207 details = addValues.Concat(details).ToDictionary(x=>x.Key,x=>x.Value); 208 209 /* Is not pot or pan */ 210 } else { 211 212 /** 213 * Creating new dictionary to merge 214 * This way we can prepend the new values to the existing dictionary 215 */ 216 Dictionary<string, Dictionary<string, string>> addValues = new Dictionary<string, Dictionary<string, string>>() { 217 { 218 /** 219 * NOTE: 220 * The same field is used for length and top diameter 221 * Pots/pans use diameter, knives use length 222 */ 223 "length", new Dictionary<string, string>(){ 224 { "text", "Length" }, 225 { "description", Pageview.Area.Item["ProductDetailLengthDescription"].ToString() }, 226 { "value", productSize }, 227 { "is-empty", string.IsNullOrEmpty(productSize).ToString() } 228 } 229 }, 230 { 231 "color", new Dictionary<string, string>(){ 232 { "text", "Color" }, 233 { "description", null }, 234 { "value", productColor }, 235 { "is-empty", string.IsNullOrEmpty(productColor).ToString() } 236 } 237 } 238 }; 239 240 /* Merge dictionaries */ 241 details = addValues.Concat(details).ToDictionary(x=>x.Key,x=>x.Value); 242 } 243 } 244 245 246 @SnippetStart("BodyClose") 247 <script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5418262f1f54ac79"></script> 248 @SnippetEnd("BodyClose") 249 @{ 250 string productVariantId = GetString("Ecom:Product.VariantID"); 251 252 SetMetaTags(productNumber, productVariantId); 253 254 // Whether eCom features should be hidden in the frontend 255 bool disableEcommerce = Boolean.Parse(Pageview.Area.Item["DisableEcommerce"].ToString()); 256 257 string selectedVariantId = GetString("Ecom:Product.SelectedVariantComboID"); 258 259 bool isMainProduct = string.IsNullOrEmpty(productVariantId) ? true : false; 260 261 string productName = GetString("Ecom:Product.Name"); 262 263 var dimensions = productSize.Split('x'); 264 265 string height = string.Empty; 266 string width = string.Empty; 267 268 if (dimensions.Count() > 1) 269 { 270 height = dimensions[0] + "cm"; 271 width = dimensions[1]; 272 } 273 274 string weight = productWeight + " kg"; 275 276 // Price 277 var productPrice = GetString("Ecom:Product.Price.PriceWithVATFormatted"); 278 279 var productNameAndVariant = GetString("Ecom:Product.Name") + ", " + GetString("Ecom:Product.SelectedVariantComboName"); 280 281 var symbolsLoop = GetLoop("NZNIQSymbols"); 282 283 string productVideo = GetString("Ecom:Product:Field.ProductVideo"); 284 285 // Media product images 286 string mainImage = GetString("Ecom:Product:Field.ProductImage"); 287 288 string imagePath; 289 List<string> imageIds = new List<string>(); 290 291 if (!string.IsNullOrEmpty(mainImage)) 292 { 293 imagePath = "https://cdn.scanpan.dk/Perfion/Image.aspx?id={{imageId}}&amp;size=1600x1200"; 294 imageIds.Add(mainImage); 295 string extraImages = GetString("Ecom:Product:Field.ProductExtraImages"); 296 if (!string.IsNullOrEmpty(extraImages)) 297 { 298 imageIds.AddRange(extraImages.Split(',')); 299 } 300 } 301 else 302 { 303 imagePath = "/Files/Templates/Designs/Scanpan/assets/images/noimage.gif"; 304 } 305 306 var numImages = imageIds.Count; 307 308 // Product guide 309 310 var guideId = GetString("Ecom:Product:Field.guide"); 311 string guidePath = string.Empty; 312 313 if (!string.IsNullOrEmpty(guideId)) 314 { 315 guidePath = string.Format("https://cdn.scanpan.dk/Perfion/File.aspx?id={0}&action=save", guideId); 316 } 317 318 319 // Get variants sorted by size (SIZ field) 320 var variants = GetLoop("VariantCombinations") 321 .OrderBy(v => OrderProductsBySize(v)) 322 .ThenBy(v => OrderProductsByVolume(v)) 323 .ThenBy(v => v.GetString("Ecom:Product:Field.COL")) 324 .ThenBy(v => v.GetDouble("Ecom:Product.Price.Price")) 325 .ToList(); 326 327 // Price 328 var priceWithVat = isMainProduct ? variants.Take(1).First().GetDouble("Ecom:Product.Price.PriceWithVAT") : GetDouble("Ecom:Product.Price.PriceWithVAT"); 329 var price = GetDouble("Ecom:Product.Price.PriceWithVAT"); 330 // Get product price or lowest variant price 331 var priceFormatted = isMainProduct ? variants.Take(1).First().GetString("Ecom:Product.Price") : GetString("Ecom:Product.Price"); 332 var vatPercentage = (GetDouble("Ecom:Product.Price.VATPercent") / 100) + 1; 333 var oldPrice = GetDouble("Ecom:Product:Field.ProductPriceBefore") * vatPercentage; 334 // See http://developer.dynamicweb-cms.com/api8/#Dynamicweb~Dynamicweb.Ecommerce.Prices.Price~GetDoublePriceFormatted.html 335 string oldPriceFormatted = string.Format("{0:0.00}", oldPrice); 336 var savingsPrice = oldPrice - price; 337 string savingsPriceFormatted = string.Format("{0:0.00}", savingsPrice); 338 //var savingsPriceFormatted = Dynamicweb.Ecommerce.Prices.Price.GetDoublePriceFormatted(savingsPrice, Dynamicweb.Ecommerce.Common.Context.Currency, false); 339 string googlePrice = price.ToString().Replace(",", "."); 340 341 double discountPercentage = Math.Round(100 - (100 / oldPrice * price)); 342 string discountPercentageFormatted = discountPercentage.ToString() + "%"; 343 344 // Add price text to main product 345 var MainProductText = isMainProduct ? "<span class='product__price__text'>From</span>" : null; 346 347 // Determine stock status 348 var stockStatus = GetString("Ecom:Product:Stock.ID"); 349 var stockStatusText = GetString("Ecom:Product:Stock.Text"); 350 var stockDeliveryText = string.Format("{0} {1}", GetString("Ecom:Product:Stock.DeliveryText"), GetString("Ecom:Product:Stock.DeliveryUnit")); 351 bool isOutOfStock = false; 352 string stockClassModifier = string.Empty; 353 string stockItemPropContent = string.Empty; 354 switch (stockStatus) 355 { 356 case "STOCKSTASTUSLINEID1": 357 case "LANGUAGEVALUE2": 358 stockClassModifier = "product__stock--in-stock"; 359 stockItemPropContent = "in_stock"; 360 break; 361 case "STOCKSTASTUSLINEID2": 362 case "LANGUAGEVALUE3": 363 stockClassModifier = "product__stock--limited-stock"; 364 stockItemPropContent = "in_stock"; 365 break; 366 case "STOCKSTASTUSLINEID3": 367 case "LANGUAGEVALUE4": 368 stockClassModifier = "product__stock--sold-out"; 369 stockItemPropContent = "out_of_stock"; 370 isOutOfStock = true; 371 break; 372 } 373 374 @* Only on Denmark ( area id 1 ) *@ 375 var productId = GetString("Ecom:Product.Number"); 376 var pageId = GetString("Ecom:Product.PrimaryOrCurrentPageID"); 377 var groupId = GetString("Ecom:Product.PrimaryOrFirstGroupID"); 378 var path = GetGlobalValue("Global:Pageview.Url").Replace('/', '#').Replace(".aspx", ""); 379 var queryCount = path.Split('#').Count(); 380 } 381 @if (isMainProduct) 382 { 383 // Disable out of stock 384 isOutOfStock = false; 385 } 386 387 <section class="product" itemscope itemtype="http://schema.org/Product"> 388 <div itemprop="brand" itemscope itemtype="http://schema.org/Brand" content="Scanpan"> 389 <meta itemprop="name" content="Scanpan"> 390 </div> 391 392 @* productNumber found in eCom/partials/product-details.cshtml *@ 393 <meta itemprop="sku" content="@productNumber"> 394 <meta itemprop="gtin8" content="@productNumber"> 395 <meta itemprop="height" content="@height"> 396 <meta itemprop="width" content="@width"> 397 <meta itemprop="weight" content="@weight"> 398 <meta itemprop="description" content="@StripHTML(GetString("Ecom:Product.ShortDescription"))"> 399 400 <div class="product__container"> 401 <div class="product__container-left"> 402 <h1 class="product__name product__name--mobile" itemprop="name">@productName</h1> 403 @if (imageIds.Any() || !string.IsNullOrEmpty(productVideo)) 404 { 405 <div class="product__image royalSlider rsUni js-royal-slider is-loading"> 406 @if (!string.IsNullOrEmpty(productVideo)) 407 { 408 <div class="product__video-slide"> 409 <video class="product__video-element js-product-video" autoplay muted controls playsinline> 410 <source src="https://cdn.scanpan.dk/Perfion/File.aspx?id=@productVideo" type="video/mp4"> 411 Your browser does not support HTML5 video. 412 </video> 413 <span class="product__video-play js-product-video-play"></span> 414 <img width="85" class="rsTmb" src="/Files/Templates/Designs/Scanpan/assets/images/play-thumbnail.png" alt="@productNameAndVariant"> 415 </div> 416 } 417 @foreach (string imageId in imageIds) 418 { 419 string imageSrc = imagePath.Replace("{{imageId}}", imageId); 420 <a class="rsImg" data-rsw="1600" data-rsh="1200" data-rsBigImg="@imageSrc?quality=75" href="@imageSrc.Replace("size=1600x1200", "size=588x441")"> 421 <img itemprop="image" width="85" class="rsTmb" src="@imageSrc.Replace("size=1600x1200", "size=85x65")" alt="@productNameAndVariant"> 422 </a> 423 } 424 </div> 425 } 426 @* Symbol splash *@ 427 @if (symbolsLoop.FirstOrDefault(item => item.GetInteger("NZPriority") == 1) != null) 428 { 429 var splash = symbolsLoop.FirstOrDefault(item => item.GetInteger("NZPriority") == 1).GetString("NZLink"); 430 <img class="splat" src="@splash?width=160&amp;format=png&amp;quality=80"> 431 } 432 </div> 433 <div class="product__container-right"> 434 <h1 class="product__name product__name--desktop" itemprop="name">@productName</h1> 435 436 <div class="product__info"> 437 <div class="product__shop-info"> 438 <form class="product__form js-product-form" autocomplete="off"> 439 @* For adding this product to the cart by submitting the wrapping form *@ 440 <input type="hidden" name="CartCmd" id="CartCmd" value="add"> 441 @GetString("Ecom:Product.Form.Multi.HiddenFields") 442 <div class="product__form-field"> 443 @foreach (LoopItem v in variants) 444 { 445 var variantId = v.GetString("Ecom:VariantCombination.VariantID"); 446 if (isMainProduct) 447 { 448 variantId = productVariantId; 449 } 450 451 // Build custom variant text due to some variants missing variant text 452 List<string> variantTexts = new List<string>() 453 { 454 v.GetString("Ecom:Product:Field.SIZ"), 455 v.GetString("Ecom:Product:Field.VOL"), 456 v.GetString("Ecom:Product:Field.COL") 457 }; 458 459 var variantText = string.Join(", ", variantTexts.Where(item => !string.IsNullOrEmpty(item))); 460 461 if (String.IsNullOrWhiteSpace(variantText)) 462 { 463 continue; 464 } 465 466 bool isChecked = (variantId == selectedVariantId); 467 string isCheckedText = isChecked ? "checked" : null; 468 string isActiveText = isChecked ? "active" : null; 469 470 <div class="product__form-radio-container radio-container js-radio-container @isActiveText"> 471 <input type="radio" checked="@isCheckedText" id="@variantText" class="product__form-radio js-product-variant-radio" data-variantlink="@v.GetString("Ecom:VariantCombination.Link.Clean")" name="variant" value="@variantId"> 472 <label class="product__form-radio-label" for="@variantText"><span class="product__form-radio-label--text">@variantText.Replace("cm,", "cm<br>")</span></label> 473 </div> 474 } 475 </div> 476 <div class="product__usp"> 477 <ul class="product__usp-list"> 478 <li class="product__usp-item">Leveringstid 2-5 virkedager</li> 479 <li class="product__usp-item">Gratis frakt fra 500 kr.</li> 480 <li class="product__usp-item">Dansk håndverk siden 1956</li> 481 </ul> 482 </div><!-- .product__usps --> 483 @if (!disableEcommerce) 484 { 485 <div class="product__offer" itemprop="offers" itemscope itemtype="http://schema.org/Offer"> 486 <link itemprop="url" href="@GetGlobalValue("Global:Pageview.Url")" /> 487 <meta itemprop="priceCurrency" content="@GetString("Ecom:Product.Currency.Code")"> 488 <meta itemprop="price" content="@googlePrice" /> 489 490 <meta itemprop="availability" content="@(isOutOfStock ? "https://schema.org/OutOfStock" : "https://schema.org/InStock")" /> 491 492 <div class="product__price"> 493 @if (oldPrice > 0) 494 { 495 <div class="product__price__current">@MainProductText@priceFormatted</div> 496 <span class="product__price__old">@oldPriceFormatted</span> 497 <span class="product__price__savings">Save @savingsPriceFormatted</span> 498 499 } 500 else 501 { 502 <div class="product__price__current">@MainProductText@priceFormatted</div> 503 } 504 </div> 505 @* Alin *@ 506 <div> 507 @* Alin -> TODO: Add translation and link to the Shipping terms page @Translate(InklMwStZzgl, "inkl. MwSt. Zzgl.", global) Translate(VersandKosten, "Versandkosten", global) *@ 508 @{ 509 var ShippingInfoPage = Pageview.Area.Item["ShippingInfoPage"]; 510 if (ShippingInfoPage != null && !string.IsNullOrEmpty(ShippingInfoPage.ToString())) 511 { 512 <p class="product-list__extra-text" style="font-size: 0.8em"> <a href="@ShippingInfoPage"> Frakt</a></p> 513 } 514 } 515 </div> 516 <div class="product__stock-wrapper"> 517 <span class="product__stock @stockClassModifier">@stockStatusText </span> 518 </div> 519 <div class="product__add-to-cart-container"> 520 @*<input class="product__quantity js-quantity-input" type="number" name="Quantity" value="1" />*@ 521 <input type="hidden" name="Quantity" value="1" /> 522 <button class="js-ga-four-add-to-cart product__form-submit product__add-to-cart js-fbq-add-to-cart @(isMainProduct ? "js-add-to-cart" : null)" type="submit" disabled="@isOutOfStock">Legg i handlekurv@(discountPercentage > 0 ? " (-" + discountPercentageFormatted + ")" : "")</button> 523 </div> 524 <style> 525 </style> 526 @if (!isOutOfStock) 527 { 528 <div class="product__availability"> 529 @* Render global message inside product info *@ 530 @{ 531 string theme = GetString("Item.Area.GlobalMessageTheme"); 532 533 int campaignDuration = GetInteger("Item.Area.GlobalMessageCampaignDuration") > 0 ? GetInteger("Item.Area.GlobalMessageCampaignDuration") : 30; 534 535 // Setting default global message 536 537 string name = "defaultMessage"; 538 539 int hour = int.Parse(Translate("product-countdown-hour", "13")); 540 541 string message = Translate("product-countdown-default", "Modtag i morgen,"); 542 543 DateTime current = DateTime.Now; 544 545 DateTime endDate = DateTime.Now.Date.Add(new TimeSpan(hour, 0, 0)); 546 547 bool hideCountDown = current.DayOfWeek == DayOfWeek.Friday && current.TimeOfDay.TotalSeconds >= 60 * 60 * hour 548 || current.DayOfWeek == DayOfWeek.Saturday 549 || current.DayOfWeek == DayOfWeek.Sunday && current.TimeOfDay.TotalSeconds <= 60 * 60 * hour; 550 551 if (hideCountDown) 552 { 553 message = Translate("product-countdown-weekend", "Vi sender din ordre på mandag kl. 13"); 554 } 555 556 if (current.TimeOfDay.TotalSeconds > 60 * 60 * hour) 557 { 558 endDate = endDate.AddDays(1); // Hour is passed 13. Adding one day to endDate 559 } 560 561 bool hideDays = false; 562 563 // Overruling default values when activated from website settings 564 565 DateTime campaignEndDate = GetDate("Item.Area.CampaignEndDate"); 566 567 bool globalMessageIsActive = GetBoolean("Item.Area.GlobalMessageIsActive"); 568 569 if (globalMessageIsActive && campaignEndDate >= DateTime.Now) 570 { 571 message = GetString("Item.Area.GlobalMessageText"); 572 endDate = campaignEndDate; 573 hideCountDown = GetBoolean("Item.Area.HideCountDown"); 574 if (!string.IsNullOrEmpty(GetString("Item.Area.GlobalMessageCampaignName"))) 575 { 576 name = GetString("Item.Area.GlobalMessageCampaignName"); 577 } 578 } 579 else 580 { 581 hideDays = true; 582 } 583 584 // Do not render section if cookie set (message dismissed) and area id not equals 1 or 30 or 34 585 if (Dynamicweb.Frontend.PageView.Current().Area.ID == 1 || Dynamicweb.Frontend.PageView.Current().Area.ID == 30 || Dynamicweb.Frontend.PageView.Current().Area.ID == 34) 586 { 587 <!--googleoff: all--> 588 <div class="product__timer js-count-down-active-state" data-id="@name" data-expires="@campaignDuration"> 589 <div class="product__timer-content"> 590 <div class="product__timer-text">@message</div> 591 @if (!hideCountDown) 592 { 593 <div class="product__timer-counter js-count-down" data-end-date="@(endDate.ToString("dd-MM-yyyy HH:mm:ss"))"> 594 <span>@Translate("product-countdown-text", "bestil inden")</span> 595 @if (!hideDays) 596 { 597 <span class="js-count-down-days"></span><span>@Translate("product-countdown-days", "d:")</span> 598 } 599 <span class="js-count-down-hours"></span><span>@Translate("product-countdown-hours", "t:")</span> 600 <span class="js-count-down-minutes"></span><span>@Translate("product-countdown-minutes", "m:")</span> 601 <span class="js-count-down-seconds"></span><span>@Translate("product-countdown-seconds", "s")</span> 602 </div> 603 } 604 </div> 605 </div> <!-- .global-message--@(theme) --> 606 <!--googleon: all--> 607 } 608 } 609 610 </div> 611 } 612 613 @{ 614 if (Pageview.Area.ID == 1) 615 { 616 <button style="margin-top:16px" id="ov-onskeskyen-generated-wish-button" class="pill" type="button">Tilføj til Ønskeskyen</button> 617 618 <script type="application/javascript" src="https://xn--nskeskyen-k8a.dk/onskeskyen-wish-button/external-wish-button.js" id="ov-onskeskyen-generate-wish-button-script"></script> 619 } 620 } 621 </div> 622 } 623 </form> 624 </div><!-- .product__shop-info --> 625 </div><!-- .product__info --> 626 </div> 627 <div class="product__container-left"> 628 <div class="product__share-container"> 629 <h2 class="product__subheader">Share this product</h2> 630 <div class="product__share addthis_sharing_toolbox"></div> 631 </div><!-- .product__share-container --> 632 <div class="js-accordion"> 633 <div class="product__tabs-container"> 634 <button class="product__tab-button active js-accordion-button" rel="product-tabs" data-target="#accordion-target-id-1">Om produktet</button> 635 636 @if (GetLoop("ProductCategories").Any(item => item.GetLoop("ProductCategoryFields").Where(subitem => subitem.GetString("Ecom:Product.CategoryField.CategoryID") == "specsList").Any())) 637 { 638 <button class="product__tab-button js-accordion-button" rel="product-tabs" href="#accordion-target-id-2">Spesifikasjoner</button> 639 } 640 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.guide"))) 641 { 642 <button class="product__tab-button js-accordion-button" rel="product-tabs" href="#accordion-target-id-3">Guides</button> 643 } 644 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.theSeries"))) 645 { 646 <button class="product__tab-button js-accordion-button" rel="product-tabs" href="#accordion-target-id-4">Om serien</button> 647 } 648 </div> 649 <div class="active product__tab-content" id="accordion-target-id-1"> 650 <div class="product__text">@GetString("Ecom:Product.ShortDescription")</div> 651 <div class="product__features"> 652 @if (symbolsLoop.Where(symbol => symbol.GetInteger("NZPriority") == 0 || symbol.GetString("NZName") == "Not_induction_compatible" || symbol.GetString("NZName") == "Ikke_til_induktion").Any()) 653 { 654 <h2 class="product__subheader">Egenskaper</h2> 655 <ul class="feature-list"> 656 657 @foreach (var symbol in symbolsLoop.Where(symbol => symbol.GetString("NZName") == "Not_induction_compatible" || symbol.GetString("NZName") == "Ikke_til_induktion")) 658 { 659 <li class="feature-list__item"> 660 <img class="feature-list__image" width="25" height="25" src="@symbol.GetString("NZLink")?height=25&amp;width=25&amp;quality=80"> 661 <span class="feature-list__item-text">@Translate(symbol.GetString("NZName"))</span> 662 </li> 663 } 664 @foreach (var symbol in symbolsLoop.Where(symbol => symbol.GetInteger("NZPriority") == 0).Where(symbol => symbol.GetString("NZName") != "Not_induction_compatible" && symbol.GetString("NZName") != "Ikke_til_induktion")) 665 { 666 <li class="feature-list__item"> 667 <img class="feature-list__image" width="25" height="25" src="@symbol.GetString("NZLink")?height=25&amp;width=25&amp;quality=80"> 668 <span class="feature-list__item-text">@Translate(symbol.GetString("NZName"))</span> 669 </li> 670 } 671 </ul> 672 } 673 </div> 674 </div> 675 <!-- This is an accordion always --> 676 @if (GetLoop("ProductCategories").Any(item => item.GetLoop("ProductCategoryFields").Where(subitem => subitem.GetString("Ecom:Product.CategoryField.CategoryID") == "specsList").Any())) 677 { 678 <div class="product__tab-content" id="accordion-target-id-2"> 679 <dl class="product__specs-list"> 680 <div class="product__specs-item"> 681 <dt class="product__specs-key">Item number</dt> 682 <dd class="product__specs-value">@GetString("Ecom:Product.Number")</dd> 683 </div> 684 @foreach (var item in GetLoop("ProductCategories").SelectMany(item => item.GetLoop("ProductCategoryFields").Where(subitem => subitem.GetString("Ecom:Product.CategoryField.CategoryID") == "specsList" && !string.IsNullOrEmpty(subitem.GetString("Ecom:Product.CategoryField.Value"))))) 685 { 686 string specsKey = item.GetString("Ecom:Product.CategoryField.Label"); 687 string toolTipText = string.Concat("ToolTip", specsKey); 688 string toolTipId = item.GetString("Ecom:Product.CategoryField.ID"); 689 690 if (item.GetString("Ecom:Product.CategoryField.ID") == "specsWithLid" && (item.GetString("Ecom:Product.CategoryField.Value").ToLower() == "ikke relevant" || item.GetString("Ecom:Product.CategoryField.Value").ToLower() == "not relevant")) 691 { 692 continue; 693 } 694 <div class="product__specs-item"> 695 <dt class="product__specs-key"> 696 @Translate(specsKey) 697 @if (Translate(toolTipText) != toolTipText) 698 { 699 <span class="product__specs-tooltip-icon js-toggle-class" data-target="#@toolTipId"> 700 <span id="@toolTipId" class="product__specs-tooltip js-tooltip">@Translate(toolTipText)</span> 701 </span> 702 } 703 </dt> 704 <dd class="product__specs-value">@Translate(item.GetString("Ecom:Product.CategoryField.Value"))</dd> 705 </div> 706 } 707 </dl> 708 </div> 709 } 710 @if (!string.IsNullOrEmpty(guidePath)) 711 { 712 <div class="product__tab-content" id="accordion-target-id-3"> 713 <div class="product__text"> 714 <a href="@guidePath"> 715 Last ned brukerveiledning 716 </a> 717 </div> 718 </div> 719 720 } 721 @if (!string.IsNullOrEmpty(GetString("Ecom:Product:Field.theSeries"))) 722 { 723 <div class="product__tab-content" id="accordion-target-id-4"> 724 <div class="product__text">@GetString("Ecom:Product:Field.theSeries")</div> 725 </div> 726 } 727 </div> 728 </div> 729 730 </div><!-- .product__container --> 731 @*GA4 tracking*@ 732 733 <div style="display:none" class="js-ga-four-product" 734 data-itemprice="@GetDouble("Ecom:Product.Price.PriceWithVAT").ToString().Replace(",", ".")" 735 data-itemvat="@GetDouble("Ecom:Product.Price.VATPercent").ToString().Replace(",", ".")" 736 data-itempriceold="@GetDouble("Ecom:Product:Field.ProductPriceBefore").ToString().Replace(",", ".")" 737 data-item_name="@GetString("Ecom:Product.Name")" 738 data-item_id="@GetString("Ecom:Product.Number")" 739 data-currency="@GetString("Ecom:Product.Currency.Code")"> 740 </div> 741 742 743 744 </section><!-- .product --> 745 @functions 746 { 747 struct Language 748 { 749 public string productId; 750 public string productVariantId; 751 public string productLanguage; 752 } 753 754 755 public static string StripHTML(string htmlString) 756 { 757 758 string pattern = @"<(.|\n)*?>"; 759 760 return Regex.Replace(htmlString, pattern, string.Empty); 761 } 762 763 764 private void SetMetaTags(string productNumber, string productVariantId) 765 { 766 var relatedLanguages = new List<Language>(); 767 768 //Create a DataReader on the default database 769 using (var myDr = Database.CreateDataReader($"SELECT ProductLanguageID, ProductID, ProductVariantID FROM EcomProducts WHERE ProductNumber='{productNumber}' AND ProductVariantID = '{productVariantId}'")) 770 { 771 while (myDr.Read()) 772 { 773 relatedLanguages.Add(new Language() 774 { 775 productId = Input.FormatString(myDr["ProductID"]), 776 productLanguage = Input.FormatString(myDr["ProductLanguageID"]), 777 productVariantId = Input.FormatString(myDr["ProductVariantID"]), 778 }); 779 } 780 } 781 782 string[] productPagesAndLanguages = ApplicationSettings.Instance.ProductPagesAndLanguageCode?.Split(';'); 783 784 if (productPagesAndLanguages == null) return; 785 786 foreach (var rl in relatedLanguages) 787 { 788 var languageService = new Dynamicweb.Ecommerce.International.LanguageService(); 789 string languageCode = languageService.GetLanguage(rl.productLanguage).Code2; 790 string page = String.Empty; 791 string culture = String.Empty; 792 var areaService = new Dynamicweb.Content.AreaService(); 793 Dynamicweb.Content.Area dkArea = areaService.GetArea(1); 794 795 string[] productPageAndLanguage = productPagesAndLanguages.FirstOrDefault(p => p.StartsWith($"{languageCode}|"))?.Split('|'); 796 797 if (productPageAndLanguage == null) 798 { 799 continue; 800 } 801 802 page = productPageAndLanguage[1]; 803 culture = productPageAndLanguage[2]; 804 805 string url = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl($"Default.aspx?ID={page}&ProductID={rl.productId}&VariantID={rl.productVariantId}"); 806 string urlLeftPart = System.Web.HttpContext.Current.Request.Url.GetLeftPart(System.UriPartial.Authority); 807 System.Web.HttpContext.Current.Items["MetaTags"] += $"<link rel=\"alternate\" href=\"{urlLeftPart}{url}\" hreflang=\"{culture}\" />"; 808 } 809 string mainImage = GetString("Ecom:Product:Field.ProductImage"); 810 System.Web.HttpContext.Current.Items["MetaTags"] += $"<meta property = og:image content = https://cdn.scanpan.dk/Perfion/Image.aspx?id={mainImage}&amp;size=600x315&fit=smart />"; 811 } 812 } 813 @SnippetStart("Tracking") 814 <script type="text/javascript"> 815 // FB view tracking 816 fbq('track', 'ViewContent', { 817 content_name: '@System.Web.HttpUtility.JavaScriptStringEncode(productName)', 818 content_category: '', 819 content_ids: ['@productNumber'], 820 content_type: 'product', 821 value: '@GetString("Ecom:Product.Price.Price")', 822 currency: '@GetString("Ecom:Product.Currency.Code")' 823 }); 824 // Click FB event 825 $('.js-fbq-add-to-cart').click(function () { 826 fbq('track', 'AddToCart', { 827 content_name: '@System.Web.HttpUtility.JavaScriptStringEncode(productName)', 828 content_category: '', 829 content_ids: ['@productNumber'], 830 content_type: 'product', 831 value: '@GetString("Ecom:Product.Price.Price")', 832 currency: '@GetString("Ecom:Product.Currency.Code")' 833 }); 834 }); 835 </script> 836 <script type="text/javascript"> 837 @{ 838 int areaId = Pageview.AreaID; 839 string priceTotal = GetString("Ecom:Product.Price.Price"); 840 841 string totalValue = areaId == 28 ? 842 System.Text.RegularExpressions.Regex.Replace(priceTotal, @"\s+", "").Replace(",", ".") : 843 priceTotal.Replace(",", "."); 844 } 845 846 var google_tag_params = { 847 ecomm_prodid: @productNumber, 848 ecomm_pagetype: 'product', 849 ecomm_totalvalue: '@totalValue' 850 }; 851 </script> 852 <script type="text/javascript"> 853 /* <![CDATA[ */ 854 var google_conversion_id = 976264288; 855 var google_custom_params = window.google_tag_params; 856 var google_remarketing_only = true; 857 /* ]]> */ 858 </script> 859 <script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js"> 860 </script> 861 <noscript> 862 <div style="display:inline;"> 863 <img height="1" width="1" style="border-style:none;" alt="" src="//googleads.g.doubleclick.net/pagead/viewthroughconversion/976264288/?guid=ON&amp;script=0" /> 864 </div> 865 </noscript> 866 @SnippetEnd("Tracking") 867 868 869 <script> 870 871 window.addEventListener("load", function (event) { 872 window.NzApp.GA4.trackAddToCart(".product") 873 window.NzApp.GA4.trackViewItem(".product") 874 }) 875 </script>
Scanpan
Norsk Dansk English Deutsch Nederlands
Panner
  • Inspirasjon
    • Panner til alle formål
    • Panner til induksjon
    • Non-stick-panner
    • Panner i kobber
  • Kategorier
    • Stekepanner
    • Langpanner
    • Grillpanner
    • Traktørpanner
    • Wok
    • Spesialprodukter
  • Serier
    • NYHET! Pro SB+
    • NYHET! Urban
    • TechnIQ
    • CTX
    • Pro IQ
    • Classic
    • Classic Induction
    • Se alle serier
  • Da er det alltid grillvær!
Gryter
  • Inspirasjon
    • Gryter til alle formål
    • Gryter til induksjon
    • Gryter i stål
    • Kobbergryter
  • Kategorier
    • Gryter
    • Kasseroller
    • Grytesett
    • Spesialprodukter
    • Tilbehør til gryter
  • Serier
    • NYHET! Pro SB+
    • CTX
    • Pro IQ
    • Classic Induction
    • Impact
    • Se alle serier
  • Non-stick gryter
Kniver
  • Inspirasjon
    • Kniver til alle formål
  • Kategorier
    • Kniver til kjøtt
    • Kniver til grønt
    • Kniver til brød
    • Knivsett
    • Knivsliping
    • Grillbestikk
    • Tilbehør
  • Serier
    • Classic
    • Maitre D
  • Knivmagnet
Tilbehør
  • Kategorier
    • Kjøkkenredskaper
    • Lokk
    • Rister og innsatser
    • Vedlikehold
    • Skjærebrett
  • Elegant morter
TO GO
  • Kategorier
    • Termoflaske
    • Termokrus
    • Termokopp
    • Presskande
    • Termoflaske Premium
    • Termo tumbler
    • Premium gavesett
  • Trendy termo
Serier
  • Oversikt
    • Se alle serier
    • NYHET! Pro SB+
    • NYHET! Urban
    • STS
    • Black Iron
  • Våre universer
    • Crafted by Chefs – kjøkkenutstyr Nytenkt
    • Classic – et univers av funksjonelt håndverk
    • Maitre D' – et univers av luksus og estetikk
  • Dansk siden 1956
SCANPAN Guiden

Copyright © SCANPAN Privacy Policy

For the love of good food…

Følg oss på

Facebook Instagram
Om SCANPAN
  • Historien
  • Produsert i Danmark
  • Kontakt SCANPAN
Kundeservice
  • Handelsvilkår
  • Reklamasjon
  • Forhandler (innlogging)
  • Mediebank
  • Retur
Produktinformasjon
  • Brukerveiledning – Norsk
  • SCANPANs belegg
  • Fra aluminium til kvalitetsgryter
  • Steketips og rengjøring
Kundeservice / B2B-kundeservice
+45 87 74 14 00 / +47 91 39 46 80

Mandag - torsdag 08.00-16.00

Fredag 09.00-15.30

URG 957 895 301 MVA