Artura kompositstaket m/glas 90×175 cm

Artikelnummer: 172316-1
EAN/GLN-nummer: 5703393751270
DB-nummer: 2492009

🟢 I lager (+10)
✅ Skickas inom 3–4 arbetsdagar

Underhåll Montering
SEK 2 349,00 SEK 1 996,65
InStock

Leverans från SEK 599,00

Klarna betaling Sverige

Artura kompositstaket består av skiffergrå profilskivor med en trästruktur, som skapar en vacker och spännande yta.

Fördelen med komposit är minimalt underhåll och lång hållbarhet. Brädorna kräver endast tvätt med vatten och vanlig såpa vid behov, så du behöver inte tänka på slipning och efterbehandling med träskyddsmedel/färg.

Error executing template "Designs/Swift/Paragraph/Swift_ProductSpecification_EA.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_0fe51ee60ee54728a5068cd94d202e2d.<>c__DisplayClass30_0.<RenderArticle>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\ContextAnd\Plus_Prod\Files\Templates\Designs\Swift\Paragraph\Swift_ProductSpecification_EA.cshtml:line 1250
   at CompiledRazorTemplates.Dynamic.RazorEngine_0fe51ee60ee54728a5068cd94d202e2d.<>c__DisplayClass27_0.<RenderField>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\ContextAnd\Plus_Prod\Files\Templates\Designs\Swift\Paragraph\Swift_ProductSpecification_EA.cshtml:line 983
   at CompiledRazorTemplates.Dynamic.RazorEngine_0fe51ee60ee54728a5068cd94d202e2d.<>c__DisplayClass26_0.<RenderFieldsFromList>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\ContextAnd\Plus_Prod\Files\Templates\Designs\Swift\Paragraph\Swift_ProductSpecification_EA.cshtml:line 823
   at CompiledRazorTemplates.Dynamic.RazorEngine_0fe51ee60ee54728a5068cd94d202e2d.Execute() in D:\dynamicweb.net\Solutions\ContextAnd\Plus_Prod\Files\Templates\Designs\Swift\Paragraph\Swift_ProductSpecification_EA.cshtml:line 409
   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.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb 3 @using Dynamicweb.Frontend 4 @using System.IO 5 @using Dynamicweb.Ecommerce.ProductCatalog 6 7 @functions { 8 public ProductViewModel product { get; set; } = new ProductViewModel(); 9 public string galleryLayout { get; set; } 10 public string[] supportedImageFormats { get; set; } 11 public string[] supportedVideoFormats { get; set; } 12 public string[] supportedDocumentFormats { get; set; } 13 public string[] allSupportedFormats { get; set; } 14 15 public class RatioSettings 16 { 17 public string Ratio { get; set; } 18 public string CssClass { get; set; } 19 public string CssVariable { get; set; } 20 public string Fill { get; set; } 21 } 22 23 public RatioSettings GetRatioSettings(string size = "desktop") 24 { 25 var ratioSettings = new RatioSettings(); 26 27 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 28 ratio = ratio != "0" ? ratio : ""; 29 string cssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 30 string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : ""; 31 cssClass = ratio == "fill" && size == "mobile" ? " ratio" : cssClass; 32 cssVariable = ratio == "fill" && size == "mobile" ? "--bs-aspect-ratio: 66%" : cssVariable; 33 34 ratioSettings.Ratio = ratio; 35 ratioSettings.CssClass = cssClass; 36 ratioSettings.CssVariable = cssVariable; 37 ratioSettings.Fill = ratio == "fill" ? " h-100" : ""; 38 39 return ratioSettings; 40 } 41 } 42 @{ 43 bool isVisualEditor = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) ? Convert.ToBoolean(Dynamicweb.Context.Current.Request.QueryString.Get("VisualEdit")) : false; 44 45 ProductViewModel product = new ProductViewModel(); 46 47 ProductViewModelSettings productSetting = new ProductViewModelSettings 48 { 49 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 50 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 51 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 52 ShopId = Pageview.Area.EcomShopId 53 }; 54 55 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 56 { 57 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 58 } 59 else if (Pageview.Item["DummyProduct"] != null) 60 { 61 62 string dummyProductId = ""; 63 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 64 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 65 if (productList.Products != null) 66 { 67 foreach (var p in productList.Products) { dummyProductId = p.Id; } 68 ProductViewModel dummyProduct = dummyProductId != "" ? ViewModelFactory.CreateView(productSetting, dummyProductId) : new ProductViewModel(); 69 product = dummyProduct; 70 } 71 else 72 { 73 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 74 } 75 } 76 else if (Pageview.Item["DummyProduct"] == null) 77 { 78 product = ViewModelFactory.CreateView(productSetting, Dynamicweb.Ecommerce.Services.Products.GetLastActiveProducts(1, Dynamicweb.Ecommerce.Common.Context.LanguageID, false).FirstOrDefault().Id); 79 } 80 } 81 82 @if (product?.Id != null) 83 { 84 IEnumerable<string> selectedDisplayGroupIds = Model.Item.GetRawValueString("DisplayGroups").Split(',').ToList(); 85 List<CategoryFieldViewModel> displayGroups = new List<CategoryFieldViewModel>(); 86 87 foreach (var selection in selectedDisplayGroupIds) 88 { 89 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) 90 { 91 if (selection == group.Id) 92 { 93 displayGroups.Add(group); 94 } 95 } 96 } 97 98 bool showProductFields = Model.Item.GetBoolean("ProductFields"); 99 100 bool hideTitle = Model.Item.GetBoolean("HideTitle"); 101 102 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 103 104 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-4"); 105 106 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 107 contentPadding = contentPadding == "none" ? string.Empty : contentPadding; 108 contentPadding = contentPadding == "small" ? " p-2 p-md-3" : contentPadding; 109 contentPadding = contentPadding == "large" ? " p-4 p-md-5" : contentPadding; 110 111 string layout = Model.Item.GetRawValueString("Layout", "list"); 112 string size = Model.Item.GetRawValueString("Size", "full"); 113 string gaps = size == "full" ? " gap-4" : " gap-2"; 114 115 //IDictionary<string, string> customFscFields = new Dictionary<string, string>(); 116 //var anyFscDisplayGrps = false; 117 IDictionary<string, string> customDisplayFields = new Dictionary<string, string>(); 118 var anyCustomDisplayGrps = false; 119 var montagevejledningField = product.ProductFields.TryGetValue("InstallationPdf", out FieldValueViewModel installationPdf); 120 var overensstemmelseserklæringField = product.ProductFields.TryGetValue("CompliancePdf", out FieldValueViewModel compliancePdf); 121 var styrkeberegningerField = product.ProductFields.TryGetValue("StacticCalculationsPDF", out FieldValueViewModel stacticCalculationsPDF); 122 product.ProductFields.TryGetValue("DokumentsPDF", out FieldValueViewModel dokumentsPDF); 123 var fscField = product.ProductFields.TryGetValue("FSC", out FieldValueViewModel fscTag); 124 var fscLinkField = product.ProductFields.TryGetValue("FSC_link", out FieldValueViewModel fscLinkTag); 125 var pefcLinkField = product.ProductFields.TryGetValue("PEFC_link", out FieldValueViewModel pefcLinkTag); 126 var videoLinkField = product.ProductFields.TryGetValue("VideoLink", out FieldValueViewModel videoLinkTag); 127 var iconPath = "/Files/Templates/Designs/Swift/Assets/Icons/"; 128 var imageIcon = "file-image.svg"; 129 var pdfIcon = "file-pdf.svg"; 130 var fileIcon = "file-regular.svg"; 131 var fscIcon = "file-fsc.svg"; 132 var pefcIcon = "file-pefc.svg"; 133 string colCount = ""; 134 135 136 if (!String.IsNullOrEmpty(fscTag.Value.ToString())) 137 { 138 if (fscTag.Value.ToString().ToLower().Contains("fsc")) 139 { 140 customDisplayFields.Add(fscTag.Value.ToString(), fscLinkTag.Value.ToString()); 141 } 142 if (fscTag.Value.ToString().ToLower().Contains("pefc")) 143 { 144 customDisplayFields.Add(fscTag.Value.ToString(), pefcLinkTag.Value.ToString()); 145 } 146 anyCustomDisplayGrps = true; 147 } 148 149 if (!String.IsNullOrEmpty(installationPdf.Value.ToString())) 150 { 151 customDisplayFields.Add(installationPdf.Name.ToString(), installationPdf.Value.ToString()); 152 anyCustomDisplayGrps = true; 153 } 154 if (!String.IsNullOrEmpty(compliancePdf.Value.ToString())) 155 { 156 customDisplayFields.Add(compliancePdf.Name.ToString(), compliancePdf.Value.ToString()); 157 anyCustomDisplayGrps = true; 158 } 159 if (!String.IsNullOrEmpty(stacticCalculationsPDF.Value.ToString())) 160 { 161 customDisplayFields.Add(stacticCalculationsPDF.Name.ToString(), stacticCalculationsPDF.Value.ToString()); 162 anyCustomDisplayGrps = true; 163 } 164 if (!String.IsNullOrEmpty(dokumentsPDF.Value.ToString())) 165 { 166 customDisplayFields.Add(dokumentsPDF.Name.ToString(), dokumentsPDF.Value.ToString()); 167 anyCustomDisplayGrps = true; 168 } 169 if (!String.IsNullOrEmpty(videoLinkTag.Value.ToString())) 170 { 171 customDisplayFields.Add(videoLinkTag.Name.ToString(), videoLinkTag.Value.ToString()); 172 anyCustomDisplayGrps = true; 173 } 174 175 176 177 if (Pageview.IsVisualEditorMode && displayGroups.Count() == 0) 178 { 179 product.ProductFields.Clear(); 180 product.ProductFields.Add(Translate("Width"), new FieldValueViewModel { Name = Translate("Width"), Value = "99cm" }); 181 product.ProductFields.Add(Translate("Height"), new FieldValueViewModel { Name = Translate("Height"), Value = "195cm" }); 182 showProductFields = true; 183 } 184 185 if (layout == "commas") 186 { 187 gaps = size == "full" ? " gap-4" : " gap-2"; 188 189 } 190 191 <div class="grid h-100@(gaps)@(theme)@(contentPadding) item_@Model.Item.SystemName.ToLower()"> 192 @if ((product.ProductFields != null && Model.Item.GetBoolean("ProductFields")) || (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) || (displayGroups.Count != 0)) 193 { 194 if (!hideTitle) 195 { 196 <h2 class="g-col-12 @titleFontSize mb-0">@Model.Item.GetString("Title")</h2> 197 } 198 } 199 200 @if (displayGroups.Count != 0) 201 { 202 if (layout != "accordion") 203 { 204 foreach (var group in displayGroups) 205 { 206 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 207 208 if (!hideHeader) 209 { 210 <h4 class="g-col-12 h4 mb-0">@group.Name</h4> 211 } 212 213 { @RenderFieldsFromList(group.Fields, layout, colCount) } 214 } 215 } 216 else 217 { 218 <div class="g-col-12"> 219 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 220 @foreach (var group in displayGroups) 221 { 222 <div class="accordion-item"> 223 <h2 class="accordion-header" id="SpecificationHeading_@group.Id"> 224 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Id"> 225 @group.Name 226 </button> 227 </h2> 228 <div id="SpecificationItem_@group.Id" class="accordion-collapse collapse" aria-labelledby="SpecificationHeading_@group.Id" data-bs-parent="#Specifications_@Model.ID"> 229 <div class="accordion-body"> 230 @{ @RenderFieldsFromList(group.Fields, "list", colCount) } 231 </div> 232 </div> 233 </div> 234 } 235 </div> 236 </div> 237 } 238 } 239 240 @if (product.ProductFields != null && showProductFields) 241 { 242 if (product.ProductFields.Count > 0) 243 { 244 if (layout != "accordion") 245 { 246 {@RenderFieldsFromList(product.ProductFields, layout, colCount) } 247 } 248 else 249 { 250 <div class="g-col-12"> 251 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 252 <div class="accordion-item"> 253 <h2 class="accordion-header" id="SpecificationHeading_@Model.ID"> 254 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@Model.ID" aria-expanded="false" aria-controls="SpecificationItem_@Model.ID"> 255 @Translate("Specifications") 256 </button> 257 </h2> 258 <div id="SpecificationItem_@Model.ID" class="accordion-collapse" aria-labelledby="SpecificationHeading_@Model.ID" data-bs-parent="#Specifications_@Model.ID"> 259 <div class="accordion-body"> 260 @{ @RenderFieldsFromList(product.ProductFields, "List", colCount) } 261 </div> 262 </div> 263 </div> 264 </div> 265 </div> 266 } 267 } 268 } 269 270 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) 271 { 272 if (product.ProductCategories.Count > 0) 273 { 274 if (layout != "accordion") 275 { 276 foreach (var group in product.ProductCategories) 277 { 278 CategoryFieldViewModel category = group.Value; 279 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 280 281 if (!hideHeader) 282 { 283 <h4 class="g-col-12 h4 mb-0">@group.Value.Name</h4> 284 } 285 286 { @RenderFieldsFromList(category.Fields, layout, "") } 287 } 288 } 289 else 290 { 291 <div class="g-col-12"> 292 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 293 @foreach (var group in product.ProductCategories) 294 { 295 CategoryFieldViewModel category = group.Value; 296 297 <div class="accordion-item"> 298 <h2 class="accordion-header" id="SpecificationHeading_@group.Value.Id"> 299 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Value.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Value.Id"> 300 @group.Key 301 </button> 302 </h2> 303 <div id="SpecificationItem_@group.Value.Id" class="accordion-collapse" aria-labelledby="SpecificationHeading_@group.Value.Id" data-bs-parent="#Specifications_@Model.ID"> 304 <div class="accordion-body"> 305 @{ @RenderFieldsFromList(category.Fields, "list", colCount) } 306 </div> 307 </div> 308 </div> 309 } 310 </div> 311 </div> 312 } 313 } 314 } 315 316 @{ string displayGroupsList = ""; 317 string divider = ""; 318 foreach (var group in displayGroups) 319 { 320 displayGroupsList = "tab_" + group.Id + "," + "SpecificationItem_" + group.Id + divider + displayGroupsList; 321 divider = ","; 322 } } 323 324 @if (displayGroups.Count != 0) 325 { 326 if (layout != "navtabs") 327 { 328 foreach (var group in displayGroups) 329 { 330 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 331 332 if (!hideHeader) 333 { 334 <h4 class="g-col-12 h4 mb-0">@group.Name</h4> 335 } 336 337 { @RenderFieldsFromList(group.Fields, layout, colCount) } 338 } 339 } 340 else 341 { 342 bool first = true; 343 var displayNumber = 0; 344 var customDisplayGrpouPos = 3; 345 346 <div class="g-col-12 diplay-fields efa-mod d-none d-sm-block"> 347 <ul class="nav nav-pills px-3 px-md-5 px-lg-7" id="pills-tab" role="tablist"> 348 @{ foreach (var tab in displayGroups) 349 { 350 displayNumber++; 351 if (first) 352 { 353 <li class="nav-item pe-5 py-2 py-md-2" role="presentation"> 354 <button class="nav-link active text-uppercase fc-dark bg-transparent p-0 efa-mod" id="@tab.Id-tab" onclick="toggleReset('tab_@tab.Id')" data-bs-toggle="tab" data-bs-target="#tab_@tab.Id" type="button" role="tab" aria-controls="@tab.Id" aria-selected="true">@tab.Name</button> 355 </li> 356 first = false; 357 } 358 else 359 { 360 <li class="nav-item @displayGroups.Count || @displayNumber pe-5 py-2 py-md-2" role="presentation"> 361 <button class="nav-link text-uppercase fc-dark bg-transparent p-0 efa-mod" id="@tab.Id-tab" onclick="toggleReset('tab_@tab.Id')" data-bs-toggle="tab" data-bs-target="#tab_@tab.Id" type="button" role="tab" aria-controls="@tab.Id" aria-selected="false">@tab.Name</button> 362 </li> 363 } 364 if (displayNumber == customDisplayGrpouPos || (displayNumber == displayGroups.Count && displayNumber <= customDisplayGrpouPos)) 365 { 366 if (anyCustomDisplayGrps) 367 { 368 <li class="nav-item pe-5 py-2 py-md-2" role="presentation"> 369 <button class="nav-link text-uppercase fc-dark bg-transparent p-0 efa-mod" id="@Translate("Documents_downloads")-tab" onclick="toggleReset('tab_@Translate("Documents_downloads")')" data-bs-toggle="tab" data-bs-target="#tab_@Translate("Documents_downloads")" type="button" role="tab" aria-controls="@Translate("Documents_downloads")" aria-selected="false">@Translate("Documents/downloads")</button> 370 </li> 371 } 372 } 373 } 374 displayNumber = 0; } 375 </ul> 376 @{ first = true; } 377 <div class="tab-content bg-super-light efa-mod px-3 px-md-5 px-lg-7 py-4 py-md-5" id="pills-tabContent"> 378 @{ 379 foreach (var item in displayGroups) 380 { 381 displayNumber++; 382 383 if (item.Fields.Count >= 4) 384 { 385 colCount = "g-col-md-6 g-col-lg-4 g-col-xl-3"; 386 } 387 else if (item.Fields.Count == 3) 388 { 389 colCount = "g-col-md-6 g-col-lg-4"; 390 } 391 else if (item.Fields.Count == 2) 392 { 393 colCount = "g-col-md-6 g-col-lg-6"; 394 } 395 else 396 { 397 colCount = ""; 398 } 399 400 @*foreach(var field in item.Fields) { 401 <p><strong>@item.Id</strong></p> 402 <p>@field.Key</p> 403 }*@ 404 405 if (first) 406 { 407 <div class="tab-pane fade show active collapsed efa-mod" id="tab_@item.Id" role="tabpanel" aria-labelledby=""> 408 <div> 409 @{ @RenderFieldsFromList(item.Fields, "display-fields", colCount) } 410 </div> 411 <div class="readmore-overlay efa-mod"> 412 <div class="readmore-overlay_button fs-7 fc-grey efa-mod" onclick="readMore('tab_@item.Id')"> 413 @Translate("Read more") 414 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down" viewBox="0 0 16 16"> 415 <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" /> 416 </svg> 417 </div> 418 </div> 419 </div> 420 first = false; 421 } 422 else 423 { 424 425 <div class="tab-pane fade collapsed efa-mod" id="tab_@item.Id" role="tabpanel" aria-labelledby=""> 426 <div> 427 @{ @RenderFieldsFromList(item.Fields, "display-fields", colCount) } 428 </div> 429 <div class="readmore-overlay efa-mod"> 430 <div class="readmore-overlay_button fs-7 fc-grey efa-mod" onclick="readMore('tab_@item.Id')"> 431 @Translate("Read more") 432 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down" viewBox="0 0 16 16"> 433 <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" /> 434 </svg> 435 </div> 436 </div> 437 </div> 438 } 439 440 if (displayNumber == customDisplayGrpouPos || (displayNumber == displayGroups.Count && displayNumber <= customDisplayGrpouPos)) 441 { 442 if (anyCustomDisplayGrps) 443 { 444 string icon = ""; 445 446 <div class="tab-pane fade collapsed efa-mod" id="tab_@Translate("Documents_downloads")" role="tabpanel" aria-labelledby=""> 447 <div> 448 <div class="g-col-12 grid gap-0"> 449 450 @{ 451 if (customDisplayFields.Count >= 4) 452 { 453 colCount = "g-col-md-6 g-col-lg-4 g-col-xl-3"; 454 } 455 else if (customDisplayFields.Count == 3) 456 { 457 colCount = "g-col-md-6 g-col-lg-4"; 458 } 459 else if (customDisplayFields.Count == 2) 460 { 461 colCount = "g-col-md-6 g-col-lg-6"; 462 } 463 else 464 { 465 colCount = ""; 466 } 467 } 468 469 @foreach (var field in customDisplayFields) 470 { 471 if(field.Key.Contains("Video")) { 472 <div class="g-col-12 @colCount mb-3 pe-0 pe-md-4 align-items-center"> 473 @RenderVideoPreview(field.Value, field.Key) 474 </div> 475 } 476 else 477 { 478 <div class="g-col-12 @colCount mb-3 pe-0 pe-md-4 d-flex align-items-center"> 479 @if (field.Key.Contains("FSC")) 480 { 481 icon = iconPath + fscIcon; 482 } 483 else if (field.Key.Contains("PEFC")) 484 { 485 icon = iconPath + pefcIcon; 486 } 487 else if (field.Value.Contains(".pdf")) 488 { 489 icon = iconPath + pdfIcon; 490 } 491 else if (field.Value.Contains(".png") || field.Value.Contains(".jpg") || field.Value.Contains(".jpeg")) 492 { 493 icon = iconPath + imageIcon; 494 } 495 else 496 { 497 icon = iconPath + fileIcon; 498 } 499 <span class="me-2 icon-3 efa-mod"> 500 @ReadFile(icon) 501 </span> 502 <a name="@icon" class="fw-bold m-0" href="@field.Value" title="@field.Key" target="_blank" rel="noopener"> 503 <p class="m-0">@field.Key</p> 504 </a> 505 </div> 506 507 } 508 } 509 </div> 510 </div> 511 <div class="readmore-overlay efa-mod"> 512 <div class="readmore-overlay_button fs-7 fc-grey efa-mod" onclick="readMore('tab_@Translate("Documents_downloads")')"> 513 @Translate("Read more") 514 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down" viewBox="0 0 16 16"> 515 <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" /> 516 </svg> 517 </div> 518 </div> 519 </div> 520 } 521 } 522 523 } 524 525 displayNumber = 0; } 526 </div> 527 </div> 528 529 <div class="g-col-12 d-block d-sm-none"> 530 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 531 @{ 532 foreach (var group in displayGroups) 533 { 534 displayNumber++; 535 536 if (group.Fields.Count >= 4) 537 { 538 colCount = "g-col-md-6 g-col-lg-4 g-col-xl-3"; 539 } 540 else if (group.Fields.Count == 3) 541 { 542 colCount = "g-col-md-6 g-col-lg-4"; 543 } 544 else if (group.Fields.Count == 2) 545 { 546 colCount = "g-col-md-6 g-col-lg-6"; 547 } 548 else 549 { 550 colCount = ""; 551 } 552 553 <div class="accordion-item"> 554 <h2 class="accordion-header" id="SpecificationHeading_@group.Id"> 555 <button class="accordion-button collapsed text-uppercase fc-dark efa-mod" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Id"> 556 @group.Name 557 </button> 558 </h2> 559 <div id="SpecificationItem_@group.Id" class="accordion-collapse collapse collapsed efa-mod" aria-labelledby="SpecificationHeading_@group.Id" data-bs-parent="#Specifications_@Model.ID"> 560 <div class="accordion-body bg-super-light efa-mod"> 561 @{ @RenderFieldsFromList(group.Fields, "display-fields", colCount) } 562 </div> 563 <div class="readmore-overlay pb-3 efa-mod"> 564 <div class="readmore-overlay_button fs-7 fc-grey efa-mod" onclick="readMore('SpecificationItem_@group.Id')"> 565 @Translate("Read more") 566 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down" viewBox="0 0 16 16"> 567 <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" /> 568 </svg> 569 </div> 570 </div> 571 </div> 572 </div> 573 if (displayNumber == customDisplayGrpouPos || (displayNumber == displayGroups.Count && displayNumber <= customDisplayGrpouPos)) 574 { 575 if (anyCustomDisplayGrps) 576 { 577 string icon = ""; 578 579 <div class="accordion-item"> 580 <h2 class="accordion-header" id="SpecificationHeading_@Translate("Documents_downloads")"> 581 <button class="accordion-button collapsed text-uppercase fc-dark efa-mod" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@Translate("Documents_downloads")" aria-expanded="false" aria-controls="SpecificationItem_@Translate("Documents_downloads")"> 582 @Translate("Documents/downloads") 583 </button> 584 </h2> 585 <div id="SpecificationItem_@Translate("Documents_downloads")" class="accordion-collapse collapse collapsed efa-mod" aria-labelledby="SpecificationHeading_@Translate("Documents_downloads")" data-bs-parent="#Specifications_@Model.ID"> 586 <div class="accordion-body bg-super-light efa-mod"> 587 <div class="g-col-12 grid gap-0"> 588 589 @{ 590 if (customDisplayFields.Count >= 4) 591 { 592 colCount = "g-col-md-6 g-col-lg-4 g-col-xl-3"; 593 } 594 else if (customDisplayFields.Count == 3) 595 { 596 colCount = "g-col-md-6 g-col-lg-4"; 597 } 598 else if (customDisplayFields.Count == 2) 599 { 600 colCount = "g-col-md-6 g-col-lg-6"; 601 } 602 else 603 { 604 colCount = ""; 605 } 606 } 607 608 @foreach (var field in customDisplayFields) 609 { 610 if(field.Key.Contains("Video")) { 611 <div class="g-col-12 @colCount mb-3 pe-0 pe-md-4 d-flex align-items-start"> 612 @RenderVideoPreview(field.Value, field.Key) 613 </div> 614 615 } else { 616 <div class="g-col-12 @colCount mb-3 pe-0 pe-md-4 d-flex align-items-start"> 617 618 @if (field.Key.Contains("FSC")) 619 { 620 icon = iconPath + fscIcon; 621 } 622 else if (field.Key.Contains("PEFC")) 623 { 624 icon = iconPath + pefcIcon; 625 } 626 else if (field.Value.Contains(".pdf")) 627 { 628 icon = iconPath + pdfIcon; 629 } 630 else if (field.Value.Contains(".png") || field.Value.Contains(".jpg") || field.Value.Contains(".jpeg")) 631 { 632 icon = iconPath + imageIcon; 633 } 634 else 635 { 636 icon = iconPath + fileIcon; 637 } 638 <span class="me-2 icon-3 efa-mod"> 639 @ReadFile(icon) 640 </span> 641 <a class="fw-bold m-0" href="@field.Value" title="@field.Key" target="_blank" rel="noopener"> 642 <p class="m-0">@field.Key</p> 643 </a> 644 645 </div> 646 } 647 } 648 </div> 649 </div> 650 <div class="readmore-overlay pb-3 efa-mod"> 651 <div class="readmore-overlay_button fs-7 fc-grey efa-mod" onclick="readMore('SpecificationItem_@Translate("Documents_downloads")')"> 652 @Translate("Read more") 653 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down" viewBox="0 0 16 16"> 654 <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" /> 655 </svg> 656 </div> 657 </div> 658 </div> 659 </div> 660 } 661 } 662 } 663 664 displayNumber = 0; 665 } 666 </div> 667 </div> 668 <script type="text/javascript"> 669 670 var displayGroups = '@displayGroupsList'; 671 var displayGroupList = displayGroups.split(','); 672 673 for (var i = 0; i < displayGroupList.length; i++) { 674 675 let elem = document.getElementById(displayGroupList[i]); 676 677 const observer = new ResizeObserver(change => { 678 const tapElem = change[0]; 679 if (tapElem.contentRect.height > 600) { 680 elem.classList.add('readmore-container'); 681 } 682 }); 683 observer.observe(elem); 684 } 685 686 function toggleReset(id) { 687 // Reset read-more state when switching desktop tabs. 688 // This prevents the old inline onclick from throwing: "toogleReset is not defined". 689 let tabPanes = document.querySelectorAll(".tab-pane.efa-mod"); 690 tabPanes.forEach(function (pane) { 691 pane.classList.add("collapsed"); 692 }); 693 694 let element = document.getElementById(id); 695 if (element) { 696 element.classList.add("collapsed"); 697 } 698 699 let toggleButtons = document.querySelectorAll(".readmore-overlay_button"); 700 toggleButtons.forEach(function (toggleElement) { 701 let chevronIcon = toggleElement.querySelector("svg"); 702 toggleElement.innerHTML = '@Translate("Read more")'; 703 704 if (chevronIcon) { 705 toggleElement.appendChild(chevronIcon); 706 } 707 }); 708 }; 709 710 function readMore(id) { 711 let element = document.getElementById(id); 712 element.classList.toggle('collapsed'); 713 714 let toggleElement = document.querySelector(`.readmore-overlay_button[onclick="readMore('${id}')"]`); 715 if (toggleElement) { 716 let chevronIcon = toggleElement.querySelector("svg"); // Keep the chevron icon 717 toggleElement.innerHTML = element.classList.contains('collapsed') 718 ? '@Translate("Read more")' 719 : '@Translate("Read less")'; 720 721 if (chevronIcon) { 722 toggleElement.appendChild(chevronIcon); // Reattach the chevron icon 723 } 724 } 725 }; 726 </script> 727 } 728 } 729 730 @if (product.ProductFields != null && showProductFields) 731 { 732 if (product.ProductFields.Count > 0) 733 { 734 if (layout != "navtabs") 735 { 736 {@RenderFieldsFromList(product.ProductFields, layout, "") } 737 } 738 else 739 { 740 <div class="g-col-12"> 741 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 742 <div class="accordion-item"> 743 <h2 class="accordion-header" id="SpecificationHeading_@Model.ID"> 744 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@Model.ID" aria-expanded="false" aria-controls="SpecificationItem_@Model.ID"> 745 @Translate("Specifications") 746 </button> 747 </h2> 748 <div id="SpecificationItem_@Model.ID" class="accordion-collapse" aria-labelledby="SpecificationHeading_@Model.ID" data-bs-parent="#Specifications_@Model.ID"> 749 <div class="accordion-body"> 750 @{ @RenderFieldsFromList(product.ProductFields, "List", colCount) } 751 </div> 752 </div> 753 </div> 754 </div> 755 </div> 756 } 757 } 758 } 759 760 @if (product.ProductCategories != null && Model.Item.GetBoolean("CategoryFields")) 761 { 762 if (product.ProductCategories.Count > 0) 763 { 764 if (layout != "navtabs") 765 { 766 foreach (var group in product.ProductCategories) 767 { 768 CategoryFieldViewModel category = group.Value; 769 bool hideHeader = Model.Item.GetBoolean("HideGroupHeaders"); 770 771 if (!hideHeader) 772 { 773 <h4 class="g-col-12 h4 mb-0">@group.Value.Name</h4> 774 } 775 776 { @RenderFieldsFromList(category.Fields, layout, colCount) } 777 } 778 } 779 else 780 { 781 <div class="g-col-12"> 782 <div class="accordion accordion-flush w-100" id="Specifications_@Model.ID"> 783 @foreach (var group in product.ProductCategories) 784 { 785 CategoryFieldViewModel category = group.Value; 786 787 <div class="accordion-item"> 788 <h2 class="accordion-header" id="SpecificationHeading_@group.Value.Id"> 789 <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#SpecificationItem_@group.Value.Id" aria-expanded="false" aria-controls="SpecificationItem_@group.Value.Id"> 790 @group.Key 791 </button> 792 </h2> 793 <div id="SpecificationItem_@group.Value.Id" class="accordion-collapse" aria-labelledby="SpecificationHeading_@group.Value.Id" data-bs-parent="#Specifications_@Model.ID"> 794 <div class="accordion-body"> 795 @{ @RenderFieldsFromList(category.Fields, "list", colCount) } 796 </div> 797 </div> 798 </div> 799 } 800 </div> 801 </div> 802 } 803 } 804 } 805 </div> 806 } 807 else if (Pageview.IsVisualEditorMode) 808 { 809 <div class="alert alert-warning m-0">@Translate("No products available")</div> 810 } 811 812 @helper RenderFieldsFromList(Dictionary<string, FieldValueViewModel> fields, string layout, string colCount) 813 { 814 string size = Model.Item.GetRawValueString("Size", "full"); 815 string gaps = size != "full" ? " gap-1" : string.Empty; 816 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 817 818 if (layout == "display-fields") 819 { 820 <div class="g-col-12 grid gap-0"> 821 @foreach (var field in fields) 822 { 823 {@RenderField(field.Value, layout, colCount)} 824 } 825 </div> 826 } 827 if (layout == "columns") 828 { 829 <div class="g-col-12 grid@(gaps)"> 830 @foreach (var field in fields) 831 { 832 {@RenderField(field.Value, layout, "")} 833 } 834 </div> 835 } 836 if (layout == "list") 837 { 838 <dl class="g-col-12 grid@(gaps)"> 839 @foreach (var field in fields) 840 { 841 {@RenderField(field.Value, layout, "")} 842 } 843 </dl> 844 } 845 if (layout == "table") 846 { 847 string tableSize = size == "full" ? "" : " table-sm"; 848 <div class="g-col-12"> 849 <table class="table table-striped@(tableSize)"> 850 @foreach (var field in fields) 851 { 852 {@RenderField(field.Value, layout, "")} 853 } 854 </table> 855 </div> 856 } 857 if (layout == "bullets") 858 { 859 string listSize = size == "full" ? "" : "m-0 p-0 lh-1 fs-7 opacity-75"; 860 string listStyle = size == "full" ? "" : "style=\"list-style-position: inside\""; 861 <div class="g-col-12"> 862 <ul class="@listSize" @listStyle> 863 @foreach (var field in fields) 864 { 865 {@RenderField(field.Value, layout, "")} 866 } 867 </ul> 868 </div> 869 } 870 if (layout == "commas") 871 { 872 List<string> featuresList = new List<string>(); 873 874 foreach (var field in fields) 875 { 876 if (field.Value.Value is object && !string.IsNullOrEmpty(field.Value.Value.ToString())) 877 { 878 if (field.Value.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 879 { 880 List<string> options = new List<string>(); 881 foreach (FieldOptionValueViewModel option in field.Value.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) 882 { 883 if (!string.IsNullOrWhiteSpace(option.Value)) 884 { 885 if (option.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 886 { 887 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + option.Value + "\"></span>"; 888 options.Add(colorSpan); 889 } 890 else if (!string.IsNullOrEmpty(option.Value)) 891 { 892 options.Add(option.Name); 893 } 894 } 895 } 896 string optionsString = (string.Join(", ", options.Select(x => x.ToString()).ToArray())); 897 if ((Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 898 { 899 optionsString = (string.Join(" ", options.Select(x => x.ToString()).ToArray())); 900 } 901 902 if (!hideFieldLabels) 903 { 904 featuresList.Add(field.Value.Name + ": " + optionsString); 905 } 906 else 907 { 908 featuresList.Add(optionsString); 909 } 910 } 911 else 912 { 913 if (!string.IsNullOrWhiteSpace(field.Value.Value.ToString())) 914 { 915 if (field.Value.Value.ToString().Contains("#") && (Translate(field.Value.Name) == Translate("Color") || Translate(field.Value.Name) == Translate("Colour"))) 916 { 917 string colorSpan = "<span class=\"colorbox-sm\" style=\"background-color: " + field.Value.Value + "\"></span>"; 918 919 if (!hideFieldLabels) 920 { 921 featuresList.Add(field.Value.Name + ": " + colorSpan); 922 } 923 else 924 { 925 featuresList.Add(colorSpan); 926 } 927 } 928 else 929 { 930 if (!hideFieldLabels) 931 { 932 featuresList.Add(field.Value.Name + ": " + field.Value.Value.ToString()); 933 } 934 else 935 { 936 featuresList.Add(field.Value.Value.ToString()); 937 } 938 } 939 } 940 } 941 } 942 } 943 944 string featuresString = (string.Join(", ", featuresList.Select(x => x.ToString()).ToArray())); 945 946 <div class="g-col-12 opacity-75 fs-7">@featuresString</div> 947 } 948 } 949 950 @helper RenderField(FieldValueViewModel field, string layout, string colCount) 951 { 952 string size = Model.Item.GetRawValueString("Size", "full"); 953 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 954 bool hideFieldLabels = Model.Item.GetBoolean("HideFieldLabels"); 955 bool noValues = false; 956 string orderLast = ""; 957 958 if (!string.IsNullOrEmpty(fieldValue)) 959 { 960 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) 961 { 962 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 963 noValues = values.Count > 0 ? false : true; 964 } 965 } 966 967 if (!string.IsNullOrEmpty(fieldValue) && noValues == false) 968 { 969 if (layout == "display-fields") 970 { 971 if (fieldValue == "1") { 972 orderLast = "order-last"; 973 } 974 975 <div class="g-col-12 @colCount @orderLast mb-3 pe-0 pe-md-4"> 976 977 @if (field.SystemName.Contains("InspirationArticleTabId")) 978 { 979 var dummy = false; 980 if (fieldValue == "1") { 981 dummy = true; 982 } else { 983 @RenderArticle(fieldValue, dummy) 984 } 985 } 986 else 987 { 988 if (!hideFieldLabels) 989 { 990 if (field?.SystemName != "ProductLongDescription") 991 { 992 if (Dynamicweb.Ecommerce.Common.Context.LanguageID == "LANG2") 993 { 994 <p class="fw-bold m-0">@Translate(field?.Name):</p> 995 } 996 else 997 { 998 <p class="fw-bold m-0">@field.Name:</p> 999 } 1000 } 1001 } 1002 <p class="text-break m-0"> 1003 @{ @RenderFieldValue(field) } 1004 </p> 1005 } 1006 </div> 1007 } 1008 if (layout == "columns") 1009 { 1010 1011 <div class="grid g-col-6 g-col-lg-4 gap-1"> 1012 @if (!hideFieldLabels) 1013 { 1014 if (field?.SystemName != "ProductLongDescription") 1015 { 1016 if (Dynamicweb.Ecommerce.Common.Context.LanguageID == "LANG2") 1017 { 1018 <dt class="g-col-12 g-col-lg-4">@Translate(field?.Name)</dt> 1019 } 1020 else 1021 { 1022 <dt class="g-col-12 g-col-lg-4">@field?.Name</dt> 1023 } 1024 } 1025 } 1026 <dd class="g-col-12 g-col-lg-8 mb-0 text-break"> 1027 @{ @RenderFieldValue(field) } 1028 </dd> 1029 </div> 1030 } 1031 if (layout == "list") 1032 { 1033 if (!hideFieldLabels) 1034 { 1035 if (field?.SystemName != "ProductLongDescription") 1036 { 1037 if (Dynamicweb.Ecommerce.Common.Context.LanguageID == "LANG2") 1038 { 1039 <dt class="g-col-4">@Translate(field?.Name)</dt> 1040 } 1041 else 1042 { 1043 <dt class="g-col-4">@field?.Name</dt> 1044 } 1045 } 1046 } 1047 <dd class="g-col-8 mb-0 text-break"> 1048 @{ @RenderFieldValue(field) } 1049 </dd> 1050 } 1051 if (layout == "table") 1052 { 1053 <tr> 1054 @if (!hideFieldLabels) 1055 { 1056 if (field?.SystemName != "ProductLongDescription") 1057 { 1058 if (Dynamicweb.Ecommerce.Common.Context.LanguageID == "LANG2") 1059 { 1060 <th class="w-25 w-lg-50" scope="row">@Translate(field?.Name)</th> 1061 } 1062 else 1063 { 1064 <th class="w-25 w-lg-50" scope="row">@field?.Name</th> 1065 } 1066 } 1067 } 1068 <td class="text-break"> 1069 @{ @RenderFieldValue(field) } 1070 </td> 1071 </tr> 1072 } 1073 if (layout == "bullets") 1074 { 1075 <li> 1076 @if (!hideFieldLabels) 1077 { 1078 if (field?.SystemName != "ProductLongDescription") 1079 { 1080 if (Dynamicweb.Ecommerce.Common.Context.LanguageID == "LANG2") 1081 { 1082 <strong>@Translate(field?.Name)</strong> 1083 } 1084 else 1085 { 1086 <strong>@field?.Name</strong> 1087 } 1088 } 1089 } 1090 <span> 1091 @{ @RenderFieldValue(field) } 1092 </span> 1093 </li> 1094 } 1095 } 1096 } 1097 1098 @helper RenderFieldValue(FieldValueViewModel field) 1099 { 1100 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 1101 1102 bool isLink = field?.Type == "Link"; 1103 bool isColor = false; 1104 bool isBrandName = field?.SystemName == "Brand_name"; 1105 bool isYoutubeVideo = field?.SystemName == "VideoLink"; 1106 1107 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 1108 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 1109 1110 1111 if (field.Value.GetType() == typeof(System.Collections.Generic.List<Dynamicweb.Ecommerce.ProductCatalog.FieldOptionValueViewModel>)) 1112 { 1113 int valueCount = 0; 1114 System.Collections.Generic.List<FieldOptionValueViewModel> values = field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>; 1115 int totalValues = values.Count; 1116 1117 foreach (FieldOptionValueViewModel option in values) 1118 { 1119 if (!string.IsNullOrEmpty(option.Value)) 1120 { 1121 if (option.Value.Substring(0, 1) == "#") 1122 { 1123 isColor = true; 1124 } 1125 } 1126 1127 if (!isColor) 1128 { 1129 @option.Name 1130 } 1131 else 1132 { 1133 <span class="colorbox-sm" style="background-color: @option.Value" title="@option.Name"></span> 1134 } 1135 1136 if (valueCount != totalValues && valueCount < (totalValues - 1)) 1137 { 1138 if (isColor) 1139 { 1140 <text> </text> 1141 } 1142 else 1143 { 1144 <text>, </text> 1145 } 1146 } 1147 valueCount++; 1148 } 1149 } 1150 else 1151 { 1152 if (fieldValue.Substring(0, 1) == "#") 1153 { 1154 isColor = true; 1155 } 1156 1157 if (!isColor) 1158 { 1159 if (isLink) 1160 { 1161 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link"); 1162 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty; 1163 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty; 1164 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 1165 if (isYoutubeVideo) 1166 { 1167 var videoId = linktTitle; 1168 1169 videoId = videoId.StartsWith("http://") ? videoId.Replace("http://", "") : ""; 1170 1171 linktTitle = "https://img.youtube.com/vi/" + linktTitle.Substring(linktTitle.LastIndexOf('=') + 1) + "/maxresdefault.jpg"; 1172 1173 RatioSettings ratioSettings = GetRatioSettings("desktop"); 1174 1175 <div id="SmallScreenImagesThumbnails_@Model.ID" class="grid grid-2 gap-2 overflow-x-auto my-3"> 1176 <div class="border outline-none @(ratioSettings.CssClass)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-target="#SmallScreenImages_@Model.ID" data-bs-slide-to=""> 1177 <a class="d-flex align-items-center justify-content-center" href="@field.Value" @target @rel> 1178 <div class="icon-3 position-absolute text-light" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 1179 <img src="@linktTitle" alt="" class="p-0 p-lg-1 w-100 h-100" style="object-fit: contain" data-video-id="@field.Value"> 1180 </a> 1181 </div> 1182 </div> 1183 } 1184 else 1185 { 1186 <a href="@field.Value" title="@field.Name" @target @rel>@linktTitle</a> 1187 } 1188 1189 } 1190 else if (isBrandName) 1191 { 1192 <span itemprop="brand" itemtype="https://schema.org/Brand" itemscope> 1193 <span itemprop="name">@fieldValue</span> 1194 </span> 1195 } 1196 1197 else 1198 { 1199 @fieldValue 1200 } 1201 } 1202 else 1203 { 1204 <span class="colorbox-sm" style="background-color: @fieldValue" title="@fieldValue"></span> 1205 } 1206 } 1207 } 1208 1209 @helper RenderVideoPreview(string fieldValue, string fieldName) { 1210 1211 string linktTitle = !fieldValue.Contains("aspx") ? fieldValue : Translate("Go to link"); 1212 string target = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "target=\"_blank\"" : string.Empty; 1213 string rel = Pageview.AreaSettings.GetBoolean("OpenLinksInNewTab") && fieldValue.Contains("http") ? "rel=\"noopener\"" : string.Empty; 1214 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 1215 1216 var videoId = linktTitle; 1217 1218 videoId = videoId.StartsWith("http://") ? videoId.Replace("http://", "") : ""; 1219 1220 linktTitle = "https://img.youtube.com/vi/" + linktTitle.Substring(linktTitle.LastIndexOf('=') + 1) + "/maxresdefault.jpg"; 1221 1222 RatioSettings ratioSettings = GetRatioSettings("desktop"); 1223 1224 <p class="fw-bold m-0">@(fieldName):</p> 1225 <div id="SmallScreenImagesThumbnails_@Model.ID" class="grid grid-2 gap-2 overflow-x-auto my-3"> 1226 <div class="border outline-none @(ratioSettings.CssClass)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-target="#SmallScreenImages_@Model.ID" data-bs-slide-to=""> 1227 <a class="d-flex align-items-center justify-content-center" href="@fieldValue" @target @rel> 1228 <div class="icon-3 position-absolute text-light" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div> 1229 <img src="@linktTitle" alt="" class="p-0 p-lg-1 w-100 h-100" style="object-fit: contain" data-video-id="@fieldValue"> 1230 </a> 1231 </div> 1232 </div> 1233 1234 } 1235 1236 @helper RenderArticle(string fieldValue, bool dummy) { 1237 1238 if (!string.IsNullOrEmpty(fieldValue)) { 1239 1240 if (dummy) { 1241 //dummy filler 1242 } 1243 else 1244 { 1245 int id = fieldValue != "0" ? Int32.Parse(fieldValue) : 0; 1246 if (id > 0) { 1247 1248 var specialPage = Dynamicweb.Content.Services.Pages.GetPage(id); 1249 string title = specialPage.Item.GetItem("Title").ToString(); 1250 string coverImagePath = !string.IsNullOrEmpty(specialPage.Item.GetItem("CoverImage").ToString()) ? specialPage.Item.GetItem("CoverImage").ToString() : string.Empty; 1251 1252 <article class="d-flex flex-column mb-3 gap-0 theme plus_green-white_block h-100 shadow-hover overflow-hidden lift" itemscope="" itemtype="https://schema.org/CreativeWork" style="z-index:100;"> 1253 1254 <a class="w-100 " title="@specialPage.Item.GetItem("Title")" href="@specialPage.GetPageHrefValue()" tabindex="-1"> 1255 1256 <figure class="h-lg-100 overflow-hidden m-0 mx-auto ratio ratio-16x9" aria-label="@coverImagePath"> 1257 @RenderImage(coverImagePath, title, "50% 50%", "object-fit: cover", "2", "2") 1258 </figure> 1259 </a> 1260 <div class="d-flex flex-column flex-grow-1 gap-3 w-100 p-3 p-md-4"> 1261 <a class="text-decoration-none text-decoration-underline-hover" href="@specialPage.GetPageHrefValue()"> 1262 <h3 class="h3 mb-0" itemprop="headline">@specialPage.Item.GetItem("Title")</h3> 1263 </a> 1264 <p class="m-0 opacity-75">@specialPage.Item.GetItem("Summary")</p> 1265 </div> 1266 </article> 1267 } 1268 1269 } 1270 1271 } 1272 } 1273 1274 @helper RenderImage(string coverImagePath, string title, string cssPosition, string imageObjectFit, string gridSettings, string carouselSettings) 1275 { 1276 switch(coverImagePath) 1277 { 1278 case string a when a.Contains(".jpeg"): 1279 coverImagePath = coverImagePath.Substring(0, coverImagePath.IndexOf(".jpeg") + 5); 1280 break; 1281 case string b when b.Contains(".jpg"): 1282 coverImagePath = coverImagePath.Substring(0, coverImagePath.IndexOf(".jpg") + 4); 1283 break; 1284 case string c when c.Contains(".png"): 1285 coverImagePath = coverImagePath.Substring(0, coverImagePath.IndexOf(".png") + 4); 1286 break; 1287 1288 } 1289 1290 coverImagePath = Dynamicweb.Context.Current.Server.UrlEncode(coverImagePath); 1291 1292 string imgSizeSelector = "50vw"; 1293 1294 if (gridSettings == "1" || carouselSettings == "1") 1295 { 1296 imgSizeSelector = "100vw"; 1297 } 1298 else if (gridSettings == "2" || carouselSettings == "2") 1299 { 1300 imgSizeSelector = "50vw"; 1301 } 1302 else if (gridSettings == "3" || carouselSettings == "3") 1303 { 1304 imgSizeSelector = "33vw"; 1305 } 1306 else if (gridSettings == "4" || carouselSettings == "4") 1307 { 1308 imgSizeSelector = "25vw"; 1309 } 1310 else if (gridSettings == "5" || carouselSettings == "5") 1311 { 1312 imgSizeSelector = "17vw"; 1313 } 1314 1315 string coverImagePathM = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=640&quality=85&format=webp"; 1316 string coverImagePathL = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=960&quality=85&format=webp"; 1317 string coverImagePathXL = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=1280&quality=85&format=webp"; 1318 string coverImagePathXXL = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=1920&quality=85&format=webp"; 1319 string imagePathFallBack = coverImagePathM; 1320 1321 <img srcset=" 1322 @coverImagePathM 640w, 1323 @coverImagePathL 960w, 1324 @coverImagePathXL 1280w, 1325 @coverImagePathXXL 1920w" 1326 src="@imagePathFallBack" 1327 sizes="(min-width: 992px) @imgSizeSelector, 100vw" 1328 loading="lazy" 1329 decoding="async" 1330 class="img-fluid image-zoom-lg-1-hover" 1331 style="@imageObjectFit; object-position: @cssPosition;" 1332 alt="@title"> 1333 }