Error executing template "Designs/Tapas/eCom/Product/product.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_f123c1e93158489e9308128248149cf1.<>c__DisplayClass8_0.<renderTechSpecs2>b__0(TextWriter __razor_helper_writer) in E:\Websites\elma.LIVE\Files\Templates\Designs\Tapas\eCom\Product\product.cshtml:line 1280
at CompiledRazorTemplates.Dynamic.RazorEngine_f123c1e93158489e9308128248149cf1.Execute() in E:\Websites\elma.LIVE\Files\Templates\Designs\Tapas\eCom\Product\product.cshtml:line 893
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 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>>
2
3 @using Dynamicweb.Rendering;
4 @using System.Web;
5 @using Dynamicweb.Frontend;
6 @using Dynamicweb.Environment
7 @using System.Text.RegularExpressions;
8 @using NLog;
9 @using System.Net;
10 @using System.Drawing
11 @using System.IO;
12
13 @inherits RazorTemplateBase<RazorTemplateModel<Template>>
14 @using System.Web;
15 @using Dynamicweb.Rendering;
16
17 @helper renderProduct(LoopItem item, bool fourColsPerRow = false)
18 {
19 string productName = item.GetString("Ecom:Product.Name");
20 string productNameEncoded = HttpUtility.UrlEncode(item.GetString("Ecom:Product.Name"));
21 string productNumber = item.GetString("Ecom:Product.Number");
22 string productID = item.GetString("Ecom:Product.ID");
23 string productCurrency = item.GetString("Ecom:Product.Currency");
24 string productLink = item.GetString("Ecom:Product.Link.Clean");
25 string productElNo = item.GetString("Ecom:Product:Field.FirstwebElNo.Value.Clean");
26 bool productAskForPrice = item.GetBoolean("Ecom:Product:Field.FirstwebAskForPrice.Value.Clean");
27 bool testDiscount = item.GetBoolean("Ecom:Product:Field.FirstwebIsDiscountPrice.Value.Clean");
28 string productDescription = item.GetString("Ecom:Product.LongDescription");
29
30 string nettoPriceWithoutVAT = item.GetString("Ecom:Product.Price.PriceWithoutVATFormatted");//item.GetString("Firstweb:ErpPriceInfo.NettoPriceFormattedNoSymbol");
31 string nettoPriceWithVAT = item.GetString("Ecom:Product.Price.PriceWithVATFormatted");
32
33 bool discountIsDiscountPrice = item.GetBoolean("Firstweb:Product.Discount.IsDiscountPrice");
34 string discountDefaultPrice = item.GetString("Firstweb:Product.Discount.DefaultPriceFormatted");
35 string discountEndDate = item.GetString("Firstweb:Product.Discount.EndDate");
36 string discountPrice = item.GetString("Firstweb:Product.Discount.DefaultPriceWithVatFormatted");
37 string StockColor = item.GetString("Firstweb:ErpStockInfo.StockColor");
38
39 string orderLineId = item.GetString("Firstweb:OrderTemplate:Line.ID");
40 string orderTemplateId = item.GetString("Firstweb:OrderTemplate:Line.OrderTemplateID");
41 string orderLineQuantity = item.GetString("Firstweb:OrderTemplate:Line.Quantity");
42 string orderLineComment = item.GetString("Firstweb:OrderTemplate:Line.Comment");
43 bool inFavourite = item.GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count") > 0 ? true : false;
44 string inFavouriteBoolJS = inFavourite.ToString().ToLower();
45 int productInFavoritLists = item.GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count");
46 string missingImagePath = Dynamicweb.Core.Converter.ToString(Pageview.Area.Item["MissingImageLink"]);
47 bool orderTemplate = !string.IsNullOrEmpty(orderLineId);
48 bool askForPrice = item.GetBoolean("Ecom:Product:Field.FirstwebAskForPrice.Value.Clean");
49 string imageDefaultPath = item.GetString("Ecom:Product.ImageDefault.Default.Clean");
50 string imageUrl = String.Format("/admin/public/getimage.ashx?image={0}&altFmImage_path={1}&height=300&crop=5", imageDefaultPath, missingImagePath);
51 int stock = item.GetInteger("Firstweb:ErpStockInfo.StockQuantity");
52 string stockStatus = "in-stock";
53 if (stock <= 0)
54 {
55 stockStatus = "out-of-stock";
56 }
57 else if (stock == 1)
58 {
59 stockStatus = "low-stock";
60 }
61 bool noPrice = item.GetString("Ecom:Product.Price.PriceWithoutVAT") == "0,00" || item.GetString("Ecom:Product.Price.PriceWithoutVAT") == "0.00";
62 int savingPct = item.GetInteger("Firstweb:Product.Discount.SavingPct");
63 double saving = item.GetDouble("Firstweb:Product.Discount.Saving");
64 string colClass = fourColsPerRow ? "col-lg-3" : "col-lg-4";
65 string CustomerType = Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.CustomerType.GetCustomerType();
66 string languageId = item.GetString("Ecom:Product.LanguageID");
67 string country = "";
68 if (languageId == "LANG1")
69 {
70 country = "Denmark";
71 }
72 if (languageId == "LANG2")
73 {
74 country = "Sweden";
75 }
76 if (languageId == "LANG3")
77 {
78 country = "Norway";
79 }
80 if (languageId == "LANG4")
81 {
82 country = "England";
83 }
84 string primaryGroupId = item.GetString("Ecom:Product.PrimaryGroupID");
85 string primaryGroupName = "";
86
87 if (!string.IsNullOrEmpty(primaryGroupId))
88 {
89 var primaryGroup = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(primaryGroupId);
90 if (primaryGroup != null)
91 {
92 primaryGroupName = HttpUtility.HtmlEncode(primaryGroup.Name);
93 }
94 }
95
96 <!-- ko viewModel: Elma.ViewModels.ProductViewModel-->
97 <!-- ko initValue: {observable: ProductId, value:'@productID'}--><!-- /ko-->
98 <div class="col-xs-12 col-sm-6 @colClass product-list-col">
99
100 <div class="elma-card elma-card--white product-list-card">
101 <div class="product-list-card_img-ratio">
102 @if (discountIsDiscountPrice && savingPct > 0)
103 {
104 <span class="product-list-card_saving-indicator">@savingPct %</span>
105 }
106 <a href="@productLink" class="product-list-card_img-container">
107 <img src="@imageUrl" alt="@productName" class="product-list-card_img" />
108 </a>
109 @if (!String.IsNullOrEmpty(productDescription))
110 {
111 <a href="@productLink" class="product-list-card_hover-description" style="cursor:pointer;" data-bind="click: productLink.bind($data, '@productLink', '@productNameEncoded', '@productID', '@country', @saving, '@nettoPriceWithVAT', '@item.GetString("Ecom:Manufacturer.Name")', '@primaryGroupName', event)">
112 @productDescription
113 <div class="product-list-card_description-read-more">@Translate("readmore", "Læs mere")</div>
114 </a>
115 }
116 </div>
117 <a href="@productLink" class="product-list-card_information-area" data-bind="click: productLink.bind($data, '@productLink', '@productNameEncoded', '@productID', '@country', @saving, '@nettoPriceWithVAT', '@item.GetString("Ecom:Manufacturer.Name")', '@primaryGroupName', event)">
118 <p class="product-list-card_name">@productName</p>
119 <p class="product-list-card_id">
120 @Translate("Firstweb:Product.ProductInfo.Eannumber", "EAN:") @productNumber
121 </p>
122 @if (!String.IsNullOrEmpty(productElNo))
123 {
124 <p class="product-list-card_id">
125 @Translate("Firstweb:Product.ProductInfo.Elnumber", "EL-NR.:") @productElNo
126 </p>
127 }
128 </a>
129
130 <div class="product-list-card_price-area">
131 @if (!askForPrice)
132 {
133 <p class="stock-indicator stock-indicator--@stockStatus">
134 <span class="stock-text stock-text--in-stock">@Translate("Firstweb:Product.ProductInfo.Stock.instock", "På lager")</span>
135 <span class="stock-text stock-text--low-stock">@Translate("Firstweb:Product.ProductInfo.Stock.lowstock", "Lav lagerbeholdning")</span>
136 <span class="stock-text stock-text--out-of-stock">@Translate("Firstweb:Product.ProductInfo.Stock.notinstock", "Ikke på lager")</span>
137 </p>
138 }
139 @if (askForPrice)
140 {
141 <div>@RenderParagraphContent(Dynamicweb.Core.Converter.ToInt32(Pageview.Area.Item["AskForPriceParagraph"]))</div>
142 }
143 else
144 {
145 if (discountIsDiscountPrice)
146 {
147 if (CustomerType == "Privat")
148 {
149 <p class="product-list-card_price--previous">@item.GetString("Firstweb:Product.Discount.DefaultPriceWithVatFormatted")</p>
150 }
151 else
152 {
153 <p class="product-list-card_price--previous">@item.GetString("Firstweb:Product.Discount.DefaultPriceFormatted")</p>
154 }
155 }
156 <p class="product-list-card_price">
157 @if (CustomerType == "Privat")
158 {
159 <span class="product-list-card_price--current">@nettoPriceWithVAT</span> <span class="product-list-card_price--vat">@Translate("Firstweb:Product.ProductInfo.InclVat", "Incl. moms")</span>
160 }
161 else
162 {
163 <span class="product-list-card_price--current">@nettoPriceWithoutVAT</span> <span class="product-list-card_price--vat">@Translate("Firstweb:Product.ProductInfo.ExVat", "Excl. moms")</span>
164 }
165 </p>
166 }
167 </div>
168 <div class="product-list-card_button-area">
169 <a class="btn btn-secondary" href="@productLink" data-bind="click: productLink.bind($data, '@productLink', '@productNameEncoded', '@productID', '@country', @saving, '@nettoPriceWithVAT', '@item.GetString("Ecom:Manufacturer.Name")', '@primaryGroupName', event)">@Translate("readmore", "Læs mere")</a>
170 @if (!noPrice && !askForPrice)
171 {
172 <button class="btn btn-primary add-to-cart-list" data-bind="click: $parent.AddProductFromProductViewModel" data-productid="@productID" data-product-info='["@productNameEncoded", "@productID", "@country", @saving, "@nettoPriceWithVAT", "@item.GetString("Ecom:Manufacturer.Name")", "@primaryGroupName"]'>@Translate("Productlist.AddToCart", "Læg i kurv")</button>
173 }
174 </div>
175 </div>
176
177 </div>
178 <!-- /ko-->
179 }
180
181 @* Variables for the producttemplate *@
182 @{
183 string productUrl = GetString("Ecom:Product.Link.Clean");
184 productUrl = SearchEngineFriendlyURLs.GetFriendlyUrl(productUrl);
185 string eComProductCanonical = string.Empty;
186
187 if (string.IsNullOrEmpty(GetString("Ecom:Product.Canonical")) == false)
188 {
189 eComProductCanonical = String.Format("{0}://{1}{2}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host"), "" + GetString("Ecom:Product.Canonical"));
190 }
191 else
192 {
193 eComProductCanonical = String.Format("{0}://{1}{2}", GetGlobalValue("Global:Request.Scheme"), GetGlobalValue("Global:Request.Host"), "" + productUrl);
194 }
195
196 string currentProductId = GetString("Ecom:Product.ID");
197
198 //Get main webshop group breadcrumb
199 List<Dynamicweb.Ecommerce.Products.Group> breadCrumbGroupList = new List<Dynamicweb.Ecommerce.Products.Group>();
200 Dynamicweb.Ecommerce.Products.Product currentProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(currentProductId, "", Firstweb.Custom.CustomCode.DWHelper.GetLanguageId());
201 if (currentProduct != null && !String.IsNullOrEmpty(currentProduct.Id))
202 {
203 var shopGroups = currentProduct.Groups.Where(g => g.ShopId == "SHOP2");
204
205 Dynamicweb.Ecommerce.Products.Group mainShopGroup = null;
206
207 if (!String.IsNullOrEmpty(currentProduct.PrimaryGroupId))
208 {
209 mainShopGroup = shopGroups.FirstOrDefault(g => g.Id == currentProduct.PrimaryGroupId);
210 }
211
212 if (mainShopGroup == null)
213 {
214 mainShopGroup = shopGroups.FirstOrDefault();
215 }
216
217 if (mainShopGroup != null)
218 {
219 breadCrumbGroupList = Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.EcomGroups.getBreadCrumbGroupList(mainShopGroup, true);
220 }
221 }
222
223 int favouriteCount = GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count");
224 string productName = !String.IsNullOrWhiteSpace(GetString("Ecom:Product:Field.FirstwebHeadline.Value.Clean")) ? GetString("Ecom:Product:Field.FirstwebHeadline.Value.Clean") : GetString("Ecom:Product.Name");
225 string productNameEncoded = HttpUtility.UrlEncode(GetString("Ecom:Product.Name"));
226 string subHeading = GetString("Ecom:Product:Field.FirstwebSubheadline.Value.Clean");
227
228 string productNumber = GetString("Ecom:Product.Number");
229 string productId = GetString("Ecom:Product.ID");
230 string productCurrency = GetString("Ecom:Product.Currency");
231 string productLink = GetString("Ecom:Product.Link.Clean");
232
233 bool nobuy = true;
234
235 if (Dynamicweb.Frontend.PageView.Current() != null && Dynamicweb.Frontend.PageView.Current().Page != null &&
236 Dynamicweb.Frontend.PageView.Current().Page.NavigationTag != null)
237 {
238 nobuy = Dynamicweb.Frontend.PageView.Current().Page.NavigationTag.ToLower().Equals("ecom_nobuy");
239 }
240
241 var productDocuments = Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.ProductDocuments.getProductPimDocuments(productId);
242
243
244 bool askForPrice = GetBoolean("Ecom:Product:Field.FirstwebAskForPrice.Value.Clean");
245
246 string ForceStock = GetString("Firstweb:ErpStockInfo.Configuration(ForceStock)"); //Used to make the product template provider fetch stock status from visma
247
248 string iFrameWidth = Dynamicweb.Core.Converter.ToString(Pageview.Area.Item["GlobalProductVideoIframeWidth"]);
249 string videoTitle = GetString("Ecom:Product:Field.FirstwebVideoText.Value.Clean");
250 int productInFavoritLists = GetInteger("Firstweb:Ecom:Product:OrderTemplate.InTemplates.Count");
251 string userDefinedLink = GetString("Ecom:Product:Field.FirstwebVideoLink.Value");
252 bool inFavourite = productInFavoritLists > 0;
253 string inFavouriteBoolJS = inFavourite.ToString().ToLower();
254
255 string productPageID = Dynamicweb.Core.Converter.ToInt32(Pageview.Area.Item["ProductCatalogId"]).ToString();
256 string productPageHref = "/Default.aspx?ID=" + productPageID;
257 var productImages = Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.ProductImages.getProductImages(productId);
258
259 // Decide which sections to show on the page
260 bool showVideoSection = !string.IsNullOrWhiteSpace(userDefinedLink);
261 bool showDocumentSection = (productDocuments.Count > 0);
262 bool isReadMoreVisible = false;
263
264 bool printActivated = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.GetString("activatePrint"));
265
266 if (GetString("Ecom:Product.LongDescription").Length > 350)
267 {
268 isReadMoreVisible = true;
269 }
270 int stock = GetInteger("Firstweb:ErpStockInfo.StockQuantity");
271 string stockStatus = "in-stock";
272 if (stock <= 0)
273 {
274 stockStatus = "out-of-stock";
275 }
276 else if (stock == 1)
277 {
278 stockStatus = "low-stock";
279 }
280 string CustomerType = Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.CustomerType.GetCustomerType();
281 bool onDiscount = GetBoolean("Firstweb:Product.Discount.IsDiscountPrice");
282 string discountPrice = GetString("Firstweb:Product.Discount.DefaultPriceWithVatFormatted");
283 int savingPct = GetInteger("Firstweb:Product.Discount.SavingPct");
284 double saving = GetDouble("Firstweb:Product.Discount.Saving");
285
286 bool showNewSpecs = GetBoolean("Ecom:Product:Field.ShowNewSpecs.Value.Clean");
287 bool debugSpecs = Dynamicweb.Context.Current.Request.GetBoolean("debugspecs");
288 string debugSpecsOldDebugLabel = debugSpecs ? " [#OLD]" : "";
289 string debugSpecsNewDebugLabel = debugSpecs ? " [#NEW]" : "";
290
291 string languageId = GetString("Ecom:Product.LanguageID");
292 string country = "";
293 if (languageId == "LANG1")
294 {
295 country = "Denmark";
296 }
297 if (languageId == "LANG2")
298 {
299 country = "Sweden";
300 }
301 if (languageId == "LANG3")
302 {
303 country = "Norway";
304 }
305 if (languageId == "LANG4")
306 {
307 country = "England";
308 }
309 string primaryGroupId = GetString("Ecom:Product.PrimaryGroupID");
310 string primaryGroupName = "";
311
312 if (!string.IsNullOrEmpty(primaryGroupId))
313 {
314 var primaryGroup = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(primaryGroupId);
315 if (primaryGroup != null)
316 {
317 primaryGroupName = HttpUtility.HtmlEncode(primaryGroup.Name);
318 }
319 }
320
321 var HiddenProductSpecificationDisplayGroup = GetLoop("FieldDisplayGroups").FirstOrDefault(fdg => fdg.GetString("Ecom:FieldDisplayGroup.SystemName") == "Frontend_HIddenSpecificationsProductPage");
322 List<string> HiddenProductSpecificationFieldIds = new List<string>();
323
324 if (HiddenProductSpecificationDisplayGroup != null)
325 {
326 HiddenProductSpecificationFieldIds = HiddenProductSpecificationDisplayGroup.GetLoop("Fields").Select(f => f.GetString("Ecom:FieldDisplayGroup.Field.Id")).ToList();
327 }
328
329
330 }
331
332 @SnippetStart("eComCanonical")@eComProductCanonical.TrimEnd(new[] { '/' })@SnippetEnd("eComCanonical")
333
334 @inherits RazorTemplateBase<RazorTemplateModel<Template>>
335 @using Dynamicweb.Rendering;
336 @using System.Text.RegularExpressions;
337 @using System.Text;
338 @using System.Web;
339
340 @* Checkout stuff - START *@
341
342 @{
343 @functions {
344 string GetCurrentActiveStepClass(int currentStep, int activeStep)
345 {
346 return currentStep >= activeStep ? "active" : "";
347 }
348 }
349 }
350
351 @helper GetOrderLines(IEnumerable<LoopItem> Loop, string type = "checkout")
352 {
353 string CustomerType = Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.CustomerType.GetCustomerType();
354 foreach (LoopItem item in Loop)
355 {
356 string productId = item.GetString("Ecom:Product.ID");
357 string productName = item.GetString("Ecom:Product.Name");
358 string productNameEncoded = HttpUtility.UrlEncode(productName);
359 string productNumber = item.GetString("Ecom:Product.Number");
360 string orderLineUnitPrice = item.GetString("Ecom:Order:OrderLine.UnitPrice.PriceWithoutVAT");
361 string orderLineUnitPriceVat = item.GetString("Ecom:Order:OrderLine.UnitPrice.PriceWithVAT");
362 string orderLinePriceVat = item.GetString("Ecom:Order:OrderLine.TotalPriceWithProductDiscounts.PriceWithVAT");
363 string productCurrency = item.GetString("Ecom:Product.Currency.Code");
364 int orderLineQuantity = item.GetInteger("Ecom:Order:OrderLine.Quantity");
365 double saving = item.GetDouble( "Firstweb:Order.Discount.Saving");
366
367 string languageId = item.GetString("Ecom:Product.LanguageID");
368 string country = "";
369 if (languageId == "LANG1")
370 {
371 country = "Denmark";
372 }
373 if (languageId == "LANG2")
374 {
375 country = "Sweden";
376 }
377 if (languageId == "LANG3")
378 {
379 country = "Norway";
380 }
381 if (languageId == "LANG4")
382 {
383 country = "England";
384 }
385 string primaryGroupId = item.GetString("Ecom:Product.PrimaryGroupID");
386 string primaryGroupName = "";
387
388 if (!string.IsNullOrEmpty(primaryGroupId))
389 {
390 var primaryGroup = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(primaryGroupId);
391 if (primaryGroup != null)
392 {
393 primaryGroupName = HttpUtility.HtmlEncode(primaryGroup.Name);
394 }
395 }
396
397 <div class="row margin-top-half summary-orderline" data-product-info='["@productNameEncoded", "@productId", "@country", @saving, "@orderLinePriceVat", "@productCurrency", "@item.GetString("Ecom:Manufacturer.Name")", "@primaryGroupName", "@orderLineQuantity"]'>
398 <div class="col-md-7 col-sm-7 col-xs-7">
399 <strong>@productName</strong>
400 </div>
401 @if (CustomerType == "Privat")
402 {
403 <div class="col-md-5 col-sm-5 col-xs-5 text-right xs-regular-padding">
404 @orderLineQuantity @Translate("Checkout.Quantity.One", "stk.") @Translate("Checkout.Quantity.OnePrefix", "á") @orderLineUnitPriceVat <span>@productCurrency</span>
405 </div>
406 }
407 else
408 {
409 <div class="col-md-5 col-sm-5 col-xs-5 text-right xs-regular-padding">
410 @orderLineQuantity @Translate("Checkout.Quantity.One", "stk.") @Translate("Checkout.Quantity.OnePrefix", "á") @orderLineUnitPrice <span>@productCurrency</span>
411 </div>
412 }
413 </div>
414 }
415 }
416
417 @helper renderCartSteps(int currentActiveStep) {
418 <div class="row">
419
420 <div class="col-xs-3">
421 <div class="cart-step cart-step--@GetCurrentActiveStepClass(currentActiveStep, 1)">
422 <div class="cart-step_icon">
423 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="shopping-cart" class="svg-inline--fa fa-shopping-cart fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M528.12 301.319l47.273-208C578.806 78.301 567.391 64 551.99 64H159.208l-9.166-44.81C147.758 8.021 137.93 0 126.529 0H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24h69.883l70.248 343.435C147.325 417.1 136 435.222 136 456c0 30.928 25.072 56 56 56s56-25.072 56-56c0-15.674-6.447-29.835-16.824-40h209.647C430.447 426.165 424 440.326 424 456c0 30.928 25.072 56 56 56s56-25.072 56-56c0-22.172-12.888-41.332-31.579-50.405l5.517-24.276c3.413-15.018-8.002-29.319-23.403-29.319H218.117l-6.545-32h293.145c11.206 0 20.92-7.754 23.403-18.681z"></path></svg>
424 </div>
425 <p class="cart-step_name">@Translate("CartStep.Cart", "Kurv")</p>
426 <div class="cart-step_completion-indicator"></div>
427 </div>
428 </div>
429
430 <div class="col-xs-3">
431 <div class="cart-step cart-step--@GetCurrentActiveStepClass(currentActiveStep, 2)">
432 <div class="cart-step_icon">
433 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="home" class="svg-inline--fa fa-home fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M280.37 148.26L96 300.11V464a16 16 0 0 0 16 16l112.06-.29a16 16 0 0 0 15.92-16V368a16 16 0 0 1 16-16h64a16 16 0 0 1 16 16v95.64a16 16 0 0 0 16 16.05L464 480a16 16 0 0 0 16-16V300L295.67 148.26a12.19 12.19 0 0 0-15.3 0zM571.6 251.47L488 182.56V44.05a12 12 0 0 0-12-12h-56a12 12 0 0 0-12 12v72.61L318.47 43a48 48 0 0 0-61 0L4.34 251.47a12 12 0 0 0-1.6 16.9l25.5 31A12 12 0 0 0 45.15 301l235.22-193.74a12.19 12.19 0 0 1 15.3 0L530.9 301a12 12 0 0 0 16.9-1.6l25.5-31a12 12 0 0 0-1.7-16.93z"></path></svg>
434 </div>
435 <p class="cart-step_name">@Translate("CartStep.Address", "Adresse")</p>
436 <div class="cart-step_completion-indicator"></div>
437 </div>
438 </div>
439
440 <div class="col-xs-3">
441 <div class="cart-step cart-step--@GetCurrentActiveStepClass(currentActiveStep, 3)">
442 <div class="cart-step_icon">
443 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="coins" class="svg-inline--fa fa-coins fa-w-16 img-responsive" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M0 405.3V448c0 35.3 86 64 192 64s192-28.7 192-64v-42.7C342.7 434.4 267.2 448 192 448S41.3 434.4 0 405.3zM320 128c106 0 192-28.7 192-64S426 0 320 0 128 28.7 128 64s86 64 192 64zM0 300.4V352c0 35.3 86 64 192 64s192-28.7 192-64v-51.6c-41.3 34-116.9 51.6-192 51.6S41.3 334.4 0 300.4zm416 11c57.3-11.1 96-31.7 96-55.4v-42.7c-23.2 16.4-57.3 27.6-96 34.5v63.6zM192 160C86 160 0 195.8 0 240s86 80 192 80 192-35.8 192-80-86-80-192-80zm219.3 56.3c60-10.8 100.7-32 100.7-56.3v-42.7c-35.5 25.1-96.5 38.6-160.7 41.8 29.5 14.3 51.2 33.5 60 57.2z"></path></svg>
444 </div>
445 <p class="cart-step_name">@Translate("CartStep.Payment", "Betaling")</p>
446 <div class="cart-step_completion-indicator"></div>
447 </div>
448 </div>
449
450 <div class="col-xs-3">
451 <div class="cart-step cart-step--@GetCurrentActiveStepClass(currentActiveStep, 4)">
452 <div class="cart-step_icon">
453 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="check" class="svg-inline--fa fa-check fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"></path></svg>
454 </div>
455 <p class="cart-step_name">@Translate("CartStep.Receipt", "Kvittering")</p>
456 </div>
457 </div>
458
459 </div>
460 }
461
462 @* Checkout stuff - END *@
463
464
465 @* Regular functions *@
466
467 @**
468 * StringDelimiter()
469 * Takes the description texts and shortens them so
470 * they can be displayed in a "cropped" version,
471 ***@
472
473 @helper StringDelimiter(string textString, int maxLength = 20, string delimiterType = "d", string regex = " ")
474 {
475
476 var delimiterPattern = regex == " " ? new Regex(@"\s+").ToString() : new Regex(@"-").ToString();
477
478 string returnString = String.Empty;
479 string fullText = String.Empty;
480 /**
481 * Helper to delimit a long string to a custom amount of words - if used default.
482 * If delimiterType is set to custom, the regex will decide the delimier and insert a linebreak instead
483 **/
484 StringBuilder sb = new StringBuilder();
485
486 switch (delimiterType)
487 {
488 case "textLength":
489
490 // find all spaces between words
491 MatchCollection matches = Regex.Matches(textString, delimiterPattern);
492
493 int wordLimit = maxLength;
494 int wordCharLength = wordLimit * 6;
495
496 string firstFourWords = (matches.Count >= wordLimit) ? (textString.Substring(0, matches[wordLimit - 1].Index)) : (textString);
497
498 string firstFortyCharacters = textString.Substring(0, Math.Min(textString.Length, wordCharLength));
499 string restOfText = textString.Substring(Math.Min(textString.Length, wordCharLength));
500 string result = (firstFourWords.Length > wordCharLength) ? (firstFortyCharacters) : (firstFourWords);
501
502 fullText = "<p id='fullDescription' class='invisible'>" + restOfText.Trim() + "</p>";
503
504 sb.Append(result.Trim());
505 sb.Append("...");
506
507 break;
508
509 default:
510
511 MatchCollection matchesDash = Regex.Matches(textString, delimiterPattern);
512
513 if (matchesDash.Count > 0)
514 {
515 // Console.WriteLine(matchesDash[0].Index);
516 sb.Append(textString.Substring(0, matchesDash[0].Index + 1));
517 sb.Append("<br />");
518 sb.Append(textString.Substring(matchesDash[0].Index + 1));
519 }
520 else
521 {
522 // Failsafe for showing atleast some text if anything goes wrong.
523 sb.Append(textString);
524 }
525
526 break;
527 }
528
529 @sb.ToString();
530 if (fullText != String.Empty)
531 {
532 @fullText
533 }
534 }
535
536
537 @**
538 * generateVideoLink()
539 * Creates the video link from the userdefined link on the specific product.
540 * The helper supports both the full embed link,
541 * but also if the user inserts the normal youtube link.
542 **@
543
544 @helper generateVideoLink(string link, string product, string videoTitle, string iFrameWidth)
545 {
546 string youtubeEmbedUrl = "https://www.youtube.com/embed/",
547 result = string.Empty,
548 element = string.Empty;
549 string videoId = string.Empty;
550 string embedHeight = string.Empty;
551
552 if (link.Contains(youtubeEmbedUrl))
553 {
554 result = link;
555 var embedLength = youtubeEmbedUrl.Length;
556 var linkLength = link.Length;
557 var differenceInLength = linkLength - embedLength;
558 videoId = link.Substring(embedLength, differenceInLength); // get video id with substring
559 }
560 else
561 {
562 var uri = new Uri(link);
563 var query = HttpUtility.ParseQueryString(uri.Query);
564 videoId = query["v"];
565 result = youtubeEmbedUrl + videoId;
566 }
567 string videoImagePath = String.Format("https://i1.ytimg.com/vi/{0}/maxresdefault.jpg", videoId);
568
569 <figure class="product-video-container product-video-container--link" id="cover-image-container" data-bind="click: toggleCoverImage, css: {visible:isVisible}">
570 <img src="@videoImagePath" alt='@Translate("Firstweb.Ecom.Product.Details.ProductVideo", "Se ")@videoTitle' class="img-responsive center-block" />
571 <a class="big-play-button" id="play"><i class="fa fa-youtube-play big-play-icon color-primary gradient-background" aria-hidden="true"></i></a>
572 </figure>
573 <figure class="product-video-container text-center embed-responsive embed-responsive-16by9" data-bind="visible: isVisible">
574 <iframe src='@result' class='product-video-element embed-responsive-item' allowfullscreen></iframe>
575 </figure>
576 }
577
578 @if (printActivated == false)
579 {
580 <article class="product-view" data-bind="viewModel: Elma.ViewModels.ProductPageViewModel">
581
582 <section class="product-view__main">
583 <div>
584 <div class="container">
585 <div>
586 <ul class="row breadcrumb">
587 <li>
588 <a href="@productPageHref" title="@Translate("Firstweb.Content.Breadcrumbs.ProductPage", "Produkter")">@Translate("Firstweb.Content.Breadcrumbs.ProductPage", "Produkter")</a>
589 </li>
590 @foreach (var g in breadCrumbGroupList)
591 {
592 <li>
593 <a href='/Default.aspx?ID=@GetString("Ecom:Product:Page.ID")&GroupID=@g.Id' title="@g.Name">@g.Name</a>
594 </li>
595 }
596 </ul>
597 </div>
598 </div>
599 </div>
600
601 <div>
602 <section class="container">
603 <div id="product-view-details" class="product-view__details" data-bind="event: { DOMContentLoaded: gtmDataLayer() }" data-product-info='["@productNameEncoded", "@productId", "@country", @saving, "@GetString("Ecom:Product.Price.PriceWithVATFormatted")", "@GetString("Ecom:Manufacturer.Name")", "@primaryGroupName"]'>
604 <div class="row">
605 <div class="col-md-6 col-sm-12 col-xs-12 detailsBox">
606 <div class="product-view__meta">
607 <span>@Translate("Firstweb:Product.ProductInfo.Eannumber", "EAN")</span>
608 <span>@GetString("Ecom:Product.Number")</span> / <span>@Translate("Firstweb:Product.ProductInfo.Elnumber", "EL-NR")</span>
609 <span>@GetString("Ecom:Product:Field.FirstwebElNo.Value.Clean")</span>
610 </div>
611
612 <div class="product-view__headings">
613 <h1 class="product-view__heading">@productName</h1>
614 <h2 class="product-view__subheading">@subHeading</h2>
615 </div>
616
617 <div class="row" data-bind="viewModel: Tapas.ViewModels.ProductViewModel">
618
619 <div class="col-xs-12 product-view__pricing" data-bind="initValue: {observable : ProductId, value: '@GetString("Ecom:Product.ID")'}">
620 @if (!nobuy)
621 {
622 if (askForPrice)
623 {
624 <div class="row">
625 @RenderParagraphContent(Dynamicweb.Core.Converter.ToInt32(Pageview.Area.Item["AskForPriceParagraph"]))
626 </div>
627 }
628 else
629 {
630 <div class="row">
631 <div class="col-md-10 col-sm-10 col-xs-12 price">
632
633 @{
634 if (onDiscount)
635 {
636 <div class="row product-sale">
637 <div class="col-xs-12">
638 @if (CustomerType == "Privat")
639 {
640 <div class="product-old-price text-left">@GetString("Firstweb:Product.Discount.DefaultPriceWithVatFormatted")</div>
641 }
642 else
643 {
644 <div class="product-old-price text-left">@GetString("Firstweb:Product.Discount.DefaultPriceFormatted")</div>
645 }
646
647 </div>
648 </div>
649 }
650 }
651 @if (CustomerType == "Privat")
652 {
653 <div class="actual-price text-left">@GetString("Ecom:Product.Price.PriceWithVATFormatted")</div>
654 <div class="small-price-vat text-left">@Translate("Firstweb.Ecom.Product.Details.Price.No.VAT", "Pris eksl. moms ") @GetString("Ecom:Product.Price.PriceWithoutVATFormatted")</div>
655 }
656 else
657 {
658 <div class="actual-price text-left">@GetString("Ecom:Product.Price.PriceWithoutVATFormatted")</div>
659 <div class="small-price-vat text-left">@Translate("Firstweb.Ecom.Product.Details.Price.Excl.VAT", "Pris incl. moms ") @GetString("Ecom:Product.Price.PriceWithVATFormatted")</div>
660 }
661 @if (onDiscount)
662 {
663 <div class="small-price-vat text-left">@Translate("Firstweb.Ecom.Product.Details.Price.Discount.Until", "Tilbud t.o.m. ") @GetString("Firstweb:Product.Discount.EndDate")</div>
664 }
665 </div>
666 </div>
667 }
668 }
669 </div>
670 @if (!askForPrice)
671 {
672 <div class="col-xs-12">
673 <p class="stock-indicator stock-indicator--@stockStatus product-view__stock">
674 <span class="stock-text stock-text--in-stock">@Translate("Firstweb:Product.ProductInfo.Stock.instock", "På lager")</span>
675 <span class="stock-text stock-text--low-stock">@Translate("Firstweb:Product.ProductInfo.Stock.lowstock", "Lav lagerbeholdning")</span>
676 <span class="stock-text stock-text--out-of-stock">@Translate("Firstweb:Product.ProductInfo.Stock.notinstock", "Ikke på lager")</span>
677 </p>
678 </div>
679 }
680 <div class="col-xs-12 product-buttons hidden-print">
681 @if (!nobuy)
682 {
683 <div class="product-buttons__item">
684 @if (askForPrice == false)
685 {
686 <input type="hidden" value="1" class="hide" data-bind="textInput: Quantity">
687
688 if (GetString("Ecom:Product.Price.PriceWithoutVAT") == "0,00" || GetString("Ecom:Product.Price.PriceWithoutVAT") == "0.00")
689 {
690 <div class="btn btn-primary add-to-cart product-button not-active" data-bind="loadOnBool: { observableBool: $parent.CartLoading, text: '@Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.Base.JSTrimTranslation(Translate(" addproduct", "Tilføjer produkt"))' }">
691 @Translate("Firstweb.Ecom.Product.Details.Addtocart", "Køb nu")
692 </div>
693 }
694 else
695 {
696 <div class="btn btn-primary add-to-cart product-button" data-bind="click: $parent.AddProductFromProductViewModel, loadOnBool: { observableBool: $parent.CartLoading, text: '@Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.Base.JSTrimTranslation(Translate(" addproduct", "Tilføjer produkt"))' }">
697 @Translate("Firstweb.Ecom.Product.Details.Addtocart", "Køb nu")
698 </div>
699 }
700 }
701 </div>
702 }
703
704 <div class="product-buttons__item" data-bind="with: OrderTemplateViewModel">
705 <!-- ko initValue: {observable: OrderTemplateRelationCount, value:'@favouriteCount'}--><!-- /ko-->
706 <!-- ko initValue: {observable: ShowInFavourite, value: @inFavouriteBoolJS}--><!-- /ko-->
707
708 <div class="add-to-wish product-view__add-to-wish product-button"
709 data-bind="css : { showFavorite : ShowOrderTemplateDialog},
710 visible: $root.User().IsLoggedIn(),
711 click: ToggleOrderTemplateDialog">
712 <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
<style type="text/css">
.st0{fill:#97C93D;}
.st1{fill:#FFFFFF;}
</style>
<path id="Rectangle_380" class="st0" d="M6,0h28c3.3,0,6,2.7,6,6v28c0,3.3-2.7,6-6,6H6c-3.3,0-6-2.7-6-6V6C0,2.7,2.7,0,6,0z"/>
<path id="Path_581" class="st1" d="M20,30.3L18.5,29c-5.1-4.7-8.5-7.8-8.5-11.5c0-3,2.4-5.5,5.4-5.5c0,0,0.1,0,0.1,0
c1.7,0,3.4,0.8,4.5,2.1c1.1-1.3,2.8-2.1,4.5-2.1c3,0,5.5,2.4,5.5,5.4c0,0,0,0.1,0,0.1c0,3.8-3.4,6.9-8.5,11.5L20,30.3z"/>
</svg>
713 </div>
714 </div>
715
716 <div class="product-buttons__item">
717 @{
718 string httpProtocole = HttpContext.Current.Request.IsSecureConnection ? "https" : "http";
719 string printPageUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(GetPageIdByNavigationTag("ProductPrintPage")) + $"?ProductId={productId}";
720 string pageLink = String.Format("{0}://{1}{2}&activatePrint=true", httpProtocole, HttpContext.Current.Request.Url.Host, printPageUrl);
721 string pdfServiceParameter = String.Format("{0}&filename={1}.pdf", HttpUtility.UrlEncode(pageLink), HttpUtility.UrlEncode(productName));
722 string pdfLink = String.Format("https://pdfservice.1stweb.dk/?printurl={0}", pdfServiceParameter);
723 }
724 <a href="@pdfLink" target="_blank" class="print-as-pdf color-info flex-center" title="@Translate("Firstweb.Ecom.Product.Details.PrintAsPDF", "PDF")">
725 <span class="btn__icon">
726 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-pdf" class="svg-inline--fa fa-file-pdf fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M181.9 256.1c-5-16-4.9-46.9-2-46.9 8.4 0 7.6 36.9 2 46.9zm-1.7 47.2c-7.7 20.2-17.3 43.3-28.4 62.7 18.3-7 39-17.2 62.9-21.9-12.7-9.6-24.9-23.4-34.5-40.8zM86.1 428.1c0 .8 13.2-5.4 34.9-40.2-6.7 6.3-29.1 24.5-34.9 40.2zM248 160h136v328c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V24C0 10.7 10.7 0 24 0h200v136c0 13.2 10.8 24 24 24zm-8 171.8c-20-12.2-33.3-29-42.7-53.8 4.5-18.5 11.6-46.6 6.2-64.2-4.7-29.4-42.4-26.5-47.8-6.8-5 18.3-.4 44.1 8.1 77-11.6 27.6-28.7 64.6-40.8 85.8-.1 0-.1.1-.2.1-27.1 13.9-73.6 44.5-54.5 68 5.6 6.9 16 10 21.5 10 17.9 0 35.7-18 61.1-61.8 25.8-8.5 54.1-19.1 79-23.2 21.7 11.8 47.1 19.5 64 19.5 29.2 0 31.2-32 19.7-43.4-13.9-13.6-54.3-9.7-73.6-7.2zM377 105L279 7c-4.5-4.5-10.6-7-17-7h-6v128h128v-6.1c0-6.3-2.5-12.4-7-16.9zm-74.1 255.3c4.1-2.7-2.5-11.9-42.8-9 37.1 15.8 42.8 9 42.8 9z"></path></svg>
727 </span>
728 <span>@Translate("Firstweb.Ecom.Product.Details.PrintAsPDF", "PDF")</span>
729 </a>
730 </div>
731 </div>
732
733 <div class="col-xs-12 list" data-bind="visible: $root.User().IsLoggedIn(), with: OrderTemplateViewModel">
734 <div class="add-to-wish" data-bind="css : { showFavorite : ShowOrderTemplateDialog },
735 visible: $root.User().IsLoggedIn()">
736 </div>
737 <div class="favoriteDropdown product-list-favourite product-details elma-card">
738 <div>
739 <div class="toggleNewList" data-bind="css: {showNewList : OrderTemplateShowNewList}, toggleClick: OrderTemplateShowNewList">@Translate("makenewlist", "Opret ny liste")</div>
740 <select class="favField" data-bind="options: OrderTemplateList, optionsCaption:'@Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.Base.JSTrimTranslation(Translate("chooseFromList", "Vælg en liste"))', optionsText: function(item) { return item.Value.Name() + ' (' + item.Value.Count() + ') Varer' }, value: OrderTemplateSelectedList"></select>
741 <input type="text" placeholder="@Translate("favoritlistname", "Favoritliste navn")" class="bs form-control newList favField" data-bind="textInput: OrderTemplateNewListName" />
742 <input type="hidden" class="bs quantity" data-bind="textInput: OrderTemplateQuantity" value="1" />
743 <div class="save-button btn btn-primary" data-bind="click: function() { OrderTemplateShowNewList() ? CreateNewOrderTemplateList('@currentProductId') : AddProductToOrderTemplate('@currentProductId') } ">
744 @Translate("addtofavoritlist", "Gem")
745 </div>
746 </div>
747 </div>
748 </div>
749 </div>
750
751 <div class="row tableRow">
752 <div class="col-xs-12">
753 <div class="main-product-description-full">@GetString("Ecom:Product.LongDescription")</div>
754 <!-- ko initValue: {observable: readMoreBeforeText, value:'@Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.Base.JSTrimTranslation(Translate("Firstweb:Product.ProductInfo.readMore", "Læs yderligere produktinformation"))'}--><!-- /ko-->
755 <!-- ko initValue: {observable: readMoreAfterText, value: '@Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.Base.JSTrimTranslation(Translate("Firstweb:Product.ProductInfo.CloseReadMore", "Luk"))'}--><!-- /ko-->
756 <!-- ko initValue: {observable: readMoreElementName, value: '.main-product-description-full'}--><!-- /ko-->
757 <a href="#" title='@Translate("Firstweb:Product.ProductInfo.readMore", "Læs yderligere produktinformation")' class="product-view__read-more-link" role="button" data-bind="visible: isReadMoreRelevant, click: toggleReadMore">
758 <span class="elma-link js-text" data-bind="text: readMoreButtonText"></span>
759 </a>
760 </div>
761 </div>
762 </div>
763
764 <!-- Product image -->
765 <div class="col-xs-12 col-md-6" style="overflow: hidden;padding-bottom: 10px;min-height:100px;">
766 <div class="product-view__image-zoom" data-bind="click: zoomClickHandler">
767 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
768 viewBox="0 0 43 43" style="enable-background:new 0 0 43 43;" xml:space="preserve">
769 <style type="text/css">
770
771 .st69 {
772 fill: #E8E8E8;
773 }
774
775 .st420 {
776 fill: #595959;
777 }
778 </style>
779 <circle id="Ellipse_14" class="st69" cx="21.5" cy="21.5" r="21.5" />
780
781 <g>
782 <path class="st420" d="M31.8401,11.5135c-0.0008-0.0019-0.001-0.0039-0.0018-0.0058c-0.152-0.3724-0.4484-0.6692-0.8207-0.8215
783 c-0.0056-0.0023-0.0113-0.003-0.0168-0.0052c-0.1707-0.0675-0.3555-0.1074-0.5502-0.1074h-8.1475c-0.8286,0-1.5,0.6714-1.5,1.5
784 s0.6714,1.5,1.5,1.5h4.5251l-4.5007,4.501c-0.5859,0.5859-0.5859,1.5352,0,2.1211c0.293,0.293,0.6768,0.4395,1.0605,0.4395
785 s0.7676-0.1465,1.0605-0.4395l4.502-4.5023v4.5276c0,0.8281,0.6714,1.5,1.5,1.5s1.5-0.6719,1.5-1.5v-8.1475
786 C31.9506,11.8752,31.9101,11.6869,31.8401,11.5135z" />
787
788 <path class="st420" d="M20.2206,28.9496H15.696l4.5007-4.501c0.5859-0.5859,0.5859-1.5352,0-2.1211s-1.5352-0.5859-2.1211,0
789 l-4.502,4.5023v-4.5276c0-0.8281-0.6714-1.5-1.5-1.5s-1.5,0.6719-1.5,1.5v8.1475c0,0.1983,0.0405,0.3867,0.1105,0.5599
790 c0.0008,0.002,0.001,0.0038,0.0018,0.0058c0.152,0.3723,0.4484,0.6692,0.8206,0.8215c0.0058,0.0024,0.0116,0.0032,0.0174,0.0054
791 c0.1706,0.0674,0.3552,0.1073,0.5497,0.1073h8.147c0.8286,0,1.5-0.6719,1.5-1.5S21.0492,28.9496,20.2206,28.9496z" />
792
793 </g>
794 </svg>
795
796 </div>
797 @if (onDiscount)
798 {
799 <div class="product-view__saving-pct">@savingPct %</div>
800 }
801 <div id="slider" class="product-gallery" data-bind="css: { 'loaded' : loadedGallery }, lightSlider: lightSliderGalleryConfig">
802 @foreach (string imagePath in productImages)
803 {
804 string encodedImage = HttpUtility.UrlEncode(imagePath);
805
806 <div data-thumb="/admin/public/getimage.ashx?image=@encodedImage&altFmImage_path=/Files/Images/ecom/no-image.png&width=840" data-src="/admin/public/getimage.ashx?image=@encodedImage&altFmImage_path=/Files/Images/ecom/no-image.png&width=840" alt="@GetString("Ecom:Product.Name")">
807 <img src="x.gif" style="width:580px;height:440px;background-image:url(/admin/public/getimage.ashx?image=@encodedImage&altFmImage_path=/Files/Images/ecom/no-image.png&width=580&height=440&crop=5);background-size:contain;background-position:50% 50%;background-repeat:no-repeat;" alt="@GetString("Ecom:Product.Name")" />
808 </div>
809 }
810 </div>
811 </div>
812 </div>
813 </div>
814 </section>
815 </div>
816 </section>
817
818 <section class="product-info">
819 <div>
820 @{
821 LoopItem kitRelationGroup = GetLoop("ProductRelatedGroups").FirstOrDefault(g => g.GetString("Ecom:Product:RelatedGroup.Name").ToLower().Equals("kit"));
822
823 if (kitRelationGroup != null)
824 {
825 List<LoopItem> kitRelationGroupProducts = kitRelationGroup.GetLoop("Products");
826 if (kitRelationGroupProducts.Any())
827 {
828 @RenderKitRow(kitRelationGroupProducts)
829 }
830 }
831 }
832 <div class="container spacing-vert spacing-vert--padded">
833 <div class="row">
834 @if (!showNewSpecs)
835 {
836 <div class="col-xs-12 col-md-6 mobile-m-b-20">
837 <div class="elma-card elma-card--white elma-card--padded">
838 <h3 class="product-info__heading">
839 @Translate("Firstweb.Ecom.Product.Details.TechnicalData", "Tekniske Data") @debugSpecsOldDebugLabel
840 </h3>
841
842 @if (GetLoop("Firstweb.ProductSpecs").Count() > 4)
843 {
844 <div class="product-info__read-more-container" data-bind="productSpecsReadMore">
845 @renderTechSpecs()
846 <div class="product-info__read-more-toggler elma-link elma-link--grey js-toggle-read-more">
847 <span class="product-info__read-more-closed-text">@Translate("ProductDetails.ReadMore", "Vis mere")</span>
848 <span class="product-info__read-more-open-text">@Translate("ProductDetails.ReadLess", "Skjul")</span>
849 </div>
850 </div>
851 }
852 else
853 {
854 @renderTechSpecs()
855 }
856 </div>
857 </div>
858 }
859
860 @if ((showNewSpecs || debugSpecs) && GetLoop("ProductCategories").Any())
861 {
862 int totalSpecs = 0;
863 foreach (var item in GetLoop("ProductCategories"))
864 {
865 string productCategoryID = item.GetString("Ecom:Product.Category.ID");
866 totalSpecs += item.GetLoop("ProductCategoryFields")
867 .Where(pcf => !String.IsNullOrEmpty(pcf.GetString("Ecom:Product.CategoryField.Value"))
868 && !HiddenProductSpecificationFieldIds.Contains("ProductCategory|" + productCategoryID + "|" + pcf.GetString("Ecom:Product.CategoryField.ID")))
869 .Count();
870 }
871 if (totalSpecs > 0)
872 {
873 <div class="col-xs-12 col-md-6 mobile-m-b-20">
874 <div class="elma-card elma-card--white elma-card--padded">
875 <h3 class="product-info__heading">
876 @Translate("Firstweb.Ecom.Product.Details.Technicialdata", "Tekniske Data") @debugSpecsNewDebugLabel
877 </h3>
878 @if (totalSpecs > 4)
879 {
880 <div class="product-info__read-more-container" data-bind="productSpecsReadMore">
881 @renderTechSpecs2(HiddenProductSpecificationFieldIds, currentProduct)
882 <div class="product-info__read-more-toggler elma-link elma-link--grey js-toggle-read-more">
883 <span class="product-info__read-more-closed-text">@Translate("ProductDetails.ReadMore", "Vis mere")</span>
884 <span class="product-info__read-more-open-text">@Translate("ProductDetails.ReadLess", "Skjul")</span>
885 </div>
886 </div>
887 }
888 else
889 {
890 @renderTechSpecs2(HiddenProductSpecificationFieldIds, currentProduct)
891 }
892 </div>
893 </div>
894 }
895 }
896
897 @if (productDocuments.Any())
898 {
899 bool readMoreCondition = productDocuments.Count > 4;
900 string documentCountClassModifier = readMoreCondition ? "product-info__read-more-container" : "";
901 string documentCountDataBindModifier = readMoreCondition ? "productSpecsReadMore" : "";
902 <div class="col-xs-12 col-md-6">
903 <div class="elma-card elma-card--white elma-card--padded">
904 <h3 class="product-info__heading">
905 @Translate("Firstweb.Ecom.Product.Details.Download", "Download")
906 </h3>
907
908 <div class="@documentCountClassModifier" data-bind="@documentCountDataBindModifier">
909 <ul class="product-info__list js-read-more-content">
910 @foreach (var productDocument in productDocuments.OrderBy(pd => pd.DocumentPath))
911 {
912 string extensionIconSrc = "PDF";
913 if (productDocument.DocumentPath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
914 {
915 extensionIconSrc = "ZIP";
916 }
917 string docTypeLabel = Translate("productDocumentType_" + productDocument.DocumentType);
918 <li class="row">
919 <div class="col-sm-3 col-xs-12 desc-item-label">
920 <span style="display: flex;align-items: center;">
921 @if (extensionIconSrc == "PDF")
922 {
923 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-pdf" class="svg-inline--fa fa-file-pdf fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M181.9 256.1c-5-16-4.9-46.9-2-46.9 8.4 0 7.6 36.9 2 46.9zm-1.7 47.2c-7.7 20.2-17.3 43.3-28.4 62.7 18.3-7 39-17.2 62.9-21.9-12.7-9.6-24.9-23.4-34.5-40.8zM86.1 428.1c0 .8 13.2-5.4 34.9-40.2-6.7 6.3-29.1 24.5-34.9 40.2zM248 160h136v328c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V24C0 10.7 10.7 0 24 0h200v136c0 13.2 10.8 24 24 24zm-8 171.8c-20-12.2-33.3-29-42.7-53.8 4.5-18.5 11.6-46.6 6.2-64.2-4.7-29.4-42.4-26.5-47.8-6.8-5 18.3-.4 44.1 8.1 77-11.6 27.6-28.7 64.6-40.8 85.8-.1 0-.1.1-.2.1-27.1 13.9-73.6 44.5-54.5 68 5.6 6.9 16 10 21.5 10 17.9 0 35.7-18 61.1-61.8 25.8-8.5 54.1-19.1 79-23.2 21.7 11.8 47.1 19.5 64 19.5 29.2 0 31.2-32 19.7-43.4-13.9-13.6-54.3-9.7-73.6-7.2zM377 105L279 7c-4.5-4.5-10.6-7-17-7h-6v128h128v-6.1c0-6.3-2.5-12.4-7-16.9zm-74.1 255.3c4.1-2.7-2.5-11.9-42.8-9 37.1 15.8 42.8 9 42.8 9z"></path></svg>
924 }
925 else if (extensionIconSrc == "ZIP")
926 {
927 <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file-download" class="svg-inline--fa fa-file-download fa-w-12" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm76.45 211.36l-96.42 95.7c-6.65 6.61-17.39 6.61-24.04 0l-96.42-95.7C73.42 337.29 80.54 320 94.82 320H160v-80c0-8.84 7.16-16 16-16h32c8.84 0 16 7.16 16 16v80h65.18c14.28 0 21.4 17.29 11.27 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"></path></svg>
928 }
929 <span>@docTypeLabel</span>
930 </span>
931 </div>
932 <div class="col-sm-9 col-xs-12 desc-item-value">
933 <a target="_blank" class="file-download-link" href="@productDocument.DocumentPath">
934 @productDocument.FileName
935 </a>
936 </div>
937 </li>
938 }
939 </ul>
940 @if (readMoreCondition)
941 {
942 <div class="product-info__read-more-toggler elma-link elma-link--grey js-toggle-read-more">
943 <span class="product-info__read-more-closed-text">@Translate("ProductDetails.ReadMore", "Vis mere")</span>
944 <span class="product-info__read-more-open-text">@Translate("ProductDetails.ReadLess", "Skjul")</span>
945 </div>
946 }
947 </div>
948
949 </div>
950 </div>
951 }
952 </div>
953 </div>
954 </div>
955 </section>
956
957 @if (showVideoSection)
958 {
959 <section class="product-video spacing-vert spacing-vert--padded" data-bind="viewModel:Elma.ViewModels.Html5VideoViewModel">
960 <!-- ko initValue: {observable: elementSelector, value:'cover-image-container'}--><!-- /ko-->
961 <div class="container product-video__inner">
962 <div class="row">
963 <div class="col-xs-12 col-md-8 center-block">
964 @generateVideoLink(userDefinedLink, productName, videoTitle, iFrameWidth)
965 </div>
966 </div>
967 </div>
968 </section>
969 }
970
971 @{
972 int feedPageId = GetPageIdByNavigationTag("RelatedProductsService");
973 <div class="js-ribbons-async" data-feed-id="@feedPageId" data-product-id="@productId" data-print-active="@printActivated"></div>
974 }
975 </article>
976
977 }
978 else
979 {
980 @* print section: only active is activatePrint=True exists *@
981 string printHeaderImage = Dynamicweb.Core.Converter.ToString(Pageview.Area.Item["PrintHeaderImage"]);
982
983
984 <div id="pdfcontent" class="container">
985
986 <img src="@printHeaderImage">
987
988 <div class="product-view__details">
989 <div class="row">
990 <div class="col-xs-10">
991 <div class="product-view__meta">
992 <span>@Translate("Firstweb:Product.ProductInfo.Eannumber", "EAN")</span>
993 <span>@GetString("Ecom:Product.Number")</span> / <span>@Translate("Firstweb:Product.ProductInfo.Elnumber", "EL-NR")</span>
994 <span>@GetString("Ecom:Product:Field.FirstwebElNo.Value.Clean")</span>
995 </div>
996
997 <div class="product-view__headings">
998 <h1 class="product-view__heading">@productName</h1>
999 <h2 class="product-view__subheading">@subHeading</h2>
1000 </div>
1001 </div>
1002 </div>
1003
1004 <!-- Product image -->
1005 <div class="row">
1006 <div class="col-xs-12">
1007 <div id="slider" class="product-gallery" data-bind="css: { 'loaded' : loadedGallery }, lightSlider: lightSliderGalleryConfig">
1008 @foreach (string imagePath in productImages.Take(1))
1009 {
1010 string encodedImage = HttpUtility.UrlEncode(imagePath);
1011
1012 <div data-thumb="/admin/public/getimage.ashx?image=@encodedImage&altFmImage_path=/Files/Images/ecom/no-image.png&width=740" data-src="/admin/public/getimage.ashx?image=@encodedImage&altFmImage_path=/Files/Images/ecom/no-image.png&width=840" alt="@GetString("Ecom:Product.Name")">
1013 <img src="x.gif" style="width:480px;height:440px;background-image:url(/admin/public/getimage.ashx?image=@encodedImage&altFmImage_path=/Files/Images/ecom/no-image.png&width=580&height=440&crop=5);background-size:contain;background-position:50% 50%;background-repeat:no-repeat;" alt="@GetString("Ecom:Product.Name")" />
1014 </div>
1015 }
1016 </div>
1017 </div>
1018 </div>
1019
1020 <div class="row">
1021 <div class="col-xs-10">
1022 <div class="main-product-description-full">@GetString("Ecom:Product.LongDescription")</div>
1023 </div>
1024 </div>
1025 </div>
1026
1027 @if (!showNewSpecs)
1028 {
1029 <div class="full-width margin-top-desktop margin-bottom-desktop">
1030 <!-- Tab panes -->
1031 <div class="tab-content">
1032 <div role="tabpanel" class="tab-pane active" id="techspecs">
1033 <div class="col-sm-12 col-xs-12">
1034 <h4>@Translate("Firstweb.Ecom.Product.Details.Technicialdata", "Tekniske Data")</h4>
1035 @renderTechSpecs("print")
1036 </div>
1037 </div>
1038 </div>
1039 </div>
1040 }
1041 @if (showNewSpecs && GetLoop("ProductCategories").Any())
1042 {
1043
1044 <div class="full-width margin-top-desktop margin-bottom-desktop">
1045 <!-- Tab panes -->
1046 <div class="tab-content">
1047 <div role="tabpanel" class="tab-pane active" id="techspecs">
1048 <div class="col-sm-12 col-xs-12">
1049 <h4>@Translate("Firstweb.Ecom.Product.Details.Technicialdata", "Tekniske Data")</h4>
1050 @renderTechSpecs2(HiddenProductSpecificationFieldIds, currentProduct, "print")
1051 </div>
1052 </div>
1053 </div>
1054 </div>
1055 }
1056
1057 @{
1058 int feedPageId = GetPageIdByNavigationTag("RelatedProductsService");
1059 <div class="js-ribbons-async" data-feed-id="@feedPageId" data-product-id="@productId" data-print-active="@printActivated"></div>
1060 }
1061 </div>
1062
1063 }
1064
1065 @helper RenderKitRow(List<LoopItem> kitProductList)
1066 {
1067 int amountOfItemsShown = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Mobile ? 1 : 3;
1068 <div class="container spacing-vert spacing-vert--padded">
1069 <h3 class="product-related__heading">@Translate("Contents")</h3>
1070 <div class="row kit-container">
1071 <div class="col-xs-12 col-md-9 mobile-m-b-20 tablet-m-b-20 kit-carousel-container" style="padding: 0;">
1072 <div id="productCarousel" class="carousel" style="overflow: hidden; width: 100%; margin: 0 auto;">
1073 <div class="carousel-inner custom-carousel-inner" itemsShown="@amountOfItemsShown">
1074 @{
1075 foreach (LoopItem relationGroupProduct in kitProductList)
1076 {
1077 <div class="carousel-item custom-carousel-item">
1078 @{
1079 string productName = relationGroupProduct.GetString("Ecom:Product.Name");
1080 string productLink = relationGroupProduct.GetString("Ecom:Product.Link.Clean");
1081 string productID = relationGroupProduct.GetString("Ecom:Product.ID");
1082 string imageUrl = Firstweb.Custom.CustomCode.Webshop.Frontend.Helpers.ProductImages.getProductPrimaryImage(productID);
1083 string encodedImage = HttpUtility.UrlEncode(imageUrl);
1084 }
1085 <div class="col-xs-12 col-md-12 mobile-m-b-20">
1086 <div class="elma-card elma-card--white elma-card--padded elma-card--carousel">
1087 <div class="product-list-card_img-ratio">
1088 <a href="@productLink" class="product-list-card_img-container">
1089 <img src="/admin/public/getimage.ashx?image=@encodedImage&altFmImage_path=/Files/Images/ecom/no-image.png&width=840" alt="@productName" class="product-list-card_img" />
1090 </a>
1091 </div>
1092 <a href="@productLink" class="product-list-card_information-area">
1093 <p class="product-list-card_name" style="margin:0">@productName</p>
1094 </a>
1095 </div>
1096 </div>
1097 </div>
1098 }
1099 }
1100 </div>
1101
1102 <a class="left carousel-control custom-left-control" role="button">
1103 <span class="glyphicon glyphicon-chevron-left left-arrow" aria-hidden="true"></span>
1104 <span class="sr-only">@Translate("KitRelatedProduct.Carousel.LeftButton", "Previous")</span>
1105 </a>
1106 <a class="right carousel-control custom-right-control" role="button">
1107 <span class="glyphicon glyphicon-chevron-right right-arrow" aria-hidden="true"></span>
1108 <span class="sr-only">@Translate("KitRelatedProduct.Carousel.LeftButton", "Next")</span>
1109 </a>
1110 </div>
1111 </div>
1112 <div class="col-xs-12 col-md-3 kit-contents-container">
1113 <div class="elma-card elma-card--white elma-card--padded js-elma-card last-elma-card elma-card--carousel">
1114 <div class="vertical-line"></div>
1115 <div class="elma-card-text-container js-accordion-container">
1116 <h3 class="product-info__heading" style="border-bottom: 1px solid #cecece; padding-bottom: 24px;">@Translate("KitRelatedProduct.Contains", "Indeholder")</h3>
1117 <div class="full-width">
1118 <div class="tab-content">
1119 <div role="tabpanel" class="tab-pane active" id="techspecs">
1120 <ul class="col-sm-12 col-xs-12 kit-bulletpoint-container">
1121 @foreach (LoopItem relationGroupProduct in kitProductList)
1122 {
1123 <li class="" style="list-style:none; padding-bottom: 10px; font-weight: 600">
1124 @relationGroupProduct.GetString("Ecom:Product.Name")
1125 </li>
1126 }
1127 </ul>
1128 </div>
1129 </div>
1130 </div>
1131 </div>
1132 <button type="button" class="elma-card-expand-btn js-accordion-btn elma-link">
1133 <span class="js-card-button-text">@Translate("ProductDetails.KitContents.ReadMore", "Læs mere")</span>
1134 </button>
1135 </div>
1136 </div>
1137
1138 <script>
1139 document.addEventListener("DOMContentLoaded", function () {
1140 const carouselInner = document.querySelector("#productCarousel .carousel-inner");
1141 const items = document.querySelectorAll("#productCarousel .carousel-inner > div");
1142 const visibleItems = carouselInner.getAttribute("itemsShown");
1143 const itemWidth = 100 / visibleItems;
1144 const maxIndex = items.length - visibleItems;
1145 let currentIndex = 0;
1146
1147 const leftControl = document.querySelector(".left.carousel-control");
1148 const rightControl = document.querySelector(".right.carousel-control");
1149
1150 function updateCarousel() {
1151 const offset = -(currentIndex * itemWidth);
1152 carouselInner.style.transform = `translateX(${offset}%)`;
1153
1154 leftControl.style.display = currentIndex > 0 ? 'block' : 'none';
1155 rightControl.style.display = currentIndex < maxIndex ? 'block' : 'none';
1156 }
1157
1158 document.querySelector(".left.carousel-control").addEventListener("click", function () {
1159 if (currentIndex > 0) {
1160 currentIndex--;
1161 updateCarousel();
1162 }
1163 });
1164
1165 document.querySelector(".right.carousel-control").addEventListener("click", function () {
1166 if (currentIndex < maxIndex) {
1167 currentIndex++;
1168 updateCarousel();
1169 }
1170 });
1171
1172 updateCarousel();
1173
1174 window.addEventListener("resize", () => {
1175 updateCarousel();
1176 });
1177
1178
1179 function expandElmaCard() {
1180 const card = document.querySelector('.js-elma-card');
1181 const textContainer = document.querySelector('.js-accordion-container');
1182 const readMoreElement = document.querySelector('.js-accordion-btn');
1183 const buttonText = document.querySelector('.js-card-button-text');
1184
1185 if (!card) return;
1186 if (!textContainer) return;
1187 if (!readMoreElement) return;
1188 if (!buttonText) return;
1189
1190 // Detect overflow in the text container
1191 // Make sure padding is included in calculation for conditional rendering of button
1192 const parentStyle = getComputedStyle(card);
1193 const parentPadding = parseFloat(parentStyle.paddingTop);
1194 const overflowAmount = (textContainer.scrollHeight - parentPadding) - textContainer.clientHeight;
1195
1196 if (overflowAmount <= 0) return;
1197
1198 card.classList.add('text-overflow');
1199
1200 const cardHeight = card.clientHeight;
1201
1202 readMoreElement.addEventListener('click', () => {
1203 if (card.classList.contains('accordion-open')) {
1204 card.style.height = cardHeight + 'px';
1205 card.classList.remove('accordion-open');
1206
1207 buttonText.textContent = "@Translate("ProductDetails.KitContents.ReadMore", "Læs mere")";
1208 return;
1209 }
1210
1211 card.style.height = (cardHeight + overflowAmount + parentPadding) + 'px';
1212 card.classList.add('accordion-open');
1213 buttonText.textContent = "@Translate("ProductDetails.KitContents.ReadLess", "Luk")";
1214 });
1215 }
1216
1217 expandElmaCard();
1218 });
1219 </script>
1220 </div>
1221 </div>
1222
1223 }
1224
1225 @helper renderTechSpecs(string type = "regular")
1226 {
1227 if (GetLoop("Firstweb.ProductSpecs").Any())
1228 {
1229 if (type == "print")
1230 {
1231 <div class="product-info__list js-read-more-content">
1232 @foreach (LoopItem i in GetLoop("Firstweb.ProductSpecs"))
1233 {
1234 <div style="width:100%;float:left;">
1235 <p style="width:50%;float:left;"><b>@i.GetValue("SpecLabel"):</b></p>
1236 <p style="width:50%;float:left;">@i.GetValue("SpecValue")</p>
1237 </div>
1238 }
1239 </div>
1240 }
1241 else
1242 {
1243 <ul class="product-info__list js-read-more-content">
1244 @foreach (LoopItem i in GetLoop("Firstweb.ProductSpecs"))
1245 {
1246 <li class="row">
1247 <div class="col-sm-4 col-xs-12 desc-item-label">@i.GetValue("SpecLabel")</div>
1248 <div class="col-sm-8 col-xs-12 desc-item-value">@i.GetValue("SpecValue")</div>
1249 </li>
1250 }
1251 </ul>
1252 }
1253 }
1254 }
1255
1256 @helper renderTechSpecs2(List<string> hiddenProductSpecificationFieldIds, Dynamicweb.Ecommerce.Products.Product currentProduct, string type = "regular")
1257 {
1258
1259 Dictionary<string, Dictionary<string, string>> productCategoryValues = new Dictionary<string, Dictionary<string, string>>();
1260
1261 var productCategorySortOrder = Dynamicweb.Frontend.PageView.Current().AreaSettings.GetItems("CustomProductCategorySort")?
1262 .Select(x => x.GetList("Category")?.SelectedValue)?
1263 .Where(x => !string.IsNullOrEmpty(x))?
1264 .ToList();
1265
1266 LoopItem generalSpecifications = GetLoop("FieldDisplayGroups").FirstOrDefault(fdg => fdg.GetString("Ecom:FieldDisplayGroup.SystemName") == "GeneralSpecifications");
1267
1268 List<LoopItem> generalSpecificationFields = generalSpecifications.GetLoop("Fields");
1269 List<LoopItem> productCategories = GetLoop("ProductCategories");
1270
1271 @:<ul class="product-info__list js-read-more-content">
1272
1273
1274 if (generalSpecificationFields.Any(x => !string.IsNullOrEmpty(x.GetString("Ecom:FieldDisplayGroup.Field.Value"))))
1275 {
1276 <li class="row technical-group-header">
1277 <div class="col-sm-12 col-xs-12 desc-item-label" style="font-weight:bold;">@generalSpecifications.GetString("Ecom:FieldDisplayGroup.Name")</div>
1278 </li>
1279
1280 foreach (LoopItem field in generalSpecificationFields)
1281 {
1282 string value = field.GetString("Ecom:FieldDisplayGroup.Field.Value");
1283
1284 if (!String.IsNullOrEmpty(field.GetString("Ecom:FieldDisplayGroup.Field.OptionLabel")))
1285 {
1286 value = field.GetString("Ecom:FieldDisplayGroup.Field.OptionLabel");
1287 }
1288
1289 if (value.ToLower() == "false")
1290 {
1291 value = "";
1292 }
1293 else if (value.ToLower() == "true")
1294 {
1295 value = Translate("SpecificationValue:Yes", "Ja");
1296 }
1297
1298 if (!String.IsNullOrEmpty(value))
1299 {
1300 <li class="row">
1301 <div class="col-sm-4 col-xs-12 desc-item-label">@field.GetString("Ecom:FieldDisplayGroup.Field.Name"):</div>
1302 <div class="col-sm-8 col-xs-12 desc-item-value">@value</div>
1303 </li>
1304 }
1305 }
1306 }
1307
1308 if (productCategorySortOrder != null && productCategorySortOrder.Any())
1309 {
1310 productCategories = productCategories.OrderBy(x => {
1311 int index = productCategorySortOrder.IndexOf(x.GetString("Ecom:Product.Category.ID"));
1312 return index < 0 ? int.MaxValue : index;
1313 }).ToList();
1314 }
1315
1316 foreach (LoopItem productCategory in productCategories)
1317 {
1318 string productCategoryID = productCategory.GetString("Ecom:Product.Category.ID");
1319 Dictionary<string, string> categoryValues = new Dictionary<string, string>();
1320
1321 var activeCategoryFields = productCategory.GetLoop("ProductCategoryFields").Where(f => !hiddenProductSpecificationFieldIds.Contains("ProductCategory|" + productCategoryID + "|" + f.GetString("Ecom:Product.CategoryField.ID"))).ToList();
1322
1323 if (!activeCategoryFields.Any())
1324 {
1325 continue;
1326 }
1327
1328 string categoryName = productCategory.GetString("Ecom:Product.Category.Name");
1329
1330 categoryName = categoryName.Substring(categoryName.IndexOf(" ") + 1).TrimStart();
1331
1332 <li class="row technical-group-header">
1333 <div class="col-sm-12 col-xs-12 desc-item-label" style="font-weight:bold;">@categoryName</div>
1334 </li>
1335
1336 foreach (LoopItem productCategoryField in activeCategoryFields)
1337 {
1338 string value = productCategoryField.GetString("Ecom:Product.CategoryField.Value");
1339
1340 if (!String.IsNullOrEmpty(productCategoryField.GetString("Ecom:Product.CategoryField.OptionLabel")))
1341 {
1342 value = productCategoryField.GetString("Ecom:Product.CategoryField.OptionLabel");
1343 }
1344
1345 if (value.ToLower() == "false")
1346 {
1347 value = "";
1348 }
1349 else if (value.ToLower() == "true")
1350 {
1351 value = Translate("SpecificationValue:Yes", "Ja");
1352 }
1353
1354 if (!String.IsNullOrEmpty(value))
1355 {
1356
1357 string productCategoryValueKey = productCategoryField.GetString("Ecom:Product.CategoryField.Label");
1358 if (productCategoryValueKey.Contains("|"))
1359 {
1360 productCategoryValueKey = productCategoryValueKey.Substring(productCategoryValueKey.IndexOf("|") + 1).TrimStart();
1361 }
1362
1363 <li class="row">
1364 <div class="col-sm-4 col-xs-12 desc-item-label">@productCategoryValueKey:</div>
1365 <div class="col-sm-8 col-xs-12 desc-item-value">@value</div>
1366 </li>
1367
1368 }
1369 }
1370 }
1371
1372 @:</ul>
1373
1374
1375 }
1376
1377
1378 <script>
1379 function loadRibbons() {
1380 const asyncRibbonSection = document.querySelector('.js-ribbons-async');
1381 if (asyncRibbonSection != null) {
1382 const feedPageId = asyncRibbonSection.getAttribute('data-feed-id');
1383 const productId = asyncRibbonSection.getAttribute('data-product-id');
1384 const print = asyncRibbonSection.getAttribute('data-print-active') == 'True' ? "&activatePrint=true" : "";
1385 console.log(asyncRibbonSection.getAttribute('data-print-active'));
1386 if (feedPageId && productId) {
1387 fetch(`/Default.aspx?ID=${feedPageId}&ProductId=${productId}${print}&redirect=false`)
1388 .then(function (response) {
1389 return response.text();
1390 }).then(function (html) {
1391 const res = new DOMParser().parseFromString(html, "text/html");
1392 var asyncRibbonSectionFeed = res.querySelector('.js-ribbons-async-feed');
1393 asyncRibbonSection.innerHTML = asyncRibbonSectionFeed.innerHTML;
1394 }).catch(err => console.log(err));
1395 }
1396 }
1397 }
1398 loadRibbons();
1399 </script>