
Glass Sliding Door Lock "8600", Chrome Plated, MK SISO
Varenummer 14.09.420-1
Error executing template "Designs/Swift/Paragraph/Swift_ProductListFacets.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_7f4593ab194c4b09ac0b50f1df395543.<>c__DisplayClass0_0.<RenderForm>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 301 at CompiledRazorTemplates.Dynamic.RazorEngine_7f4593ab194c4b09ac0b50f1df395543.Execute() in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 94 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.Ecommerce.ProductCatalog 3 @using Dynamicweb.Frontend.Navigation 4 @using Dynamicweb.Environment 5 @using Dynamicweb.Core.Encoders 6 @using System.Web 7 @using Dynamicweb.Core 8 @using System.Linq 9 10 @{ 11 ProductListViewModel productList = new ProductListViewModel(); 12 13 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 14 { 15 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 16 } 17 18 string url = Pageview.SearchFriendlyUrl; 19 20 21 url = url.LastIndexOf("?") != -1 ? url.Substring(0, url.LastIndexOf("?")) : url; 22 23 24 25 //Fix for non-friendly urls 26 if (Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") != null) 27 { 28 string groupId = Dynamicweb.Context.Current.Request.QueryString.Get("GroupID"); 29 url += "?GroupID=" + groupId; 30 31 32 } 33 34 35 if (!url.Contains("LayoutTemplate")) 36 { 37 url += url.Contains("?") ? "&LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml" : "?LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml"; 38 } 39 40 bool facetsFound = false; 41 int selectedFacetsCount = 0; 42 43 44 45 if (productList.FacetGroups != null) 46 { 47 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 48 { 49 foreach (FacetViewModel facet in facetGroup.Facets) 50 { 51 if (facet.Options.Count() > 0) 52 { 53 facetsFound = true; 54 55 foreach (FacetOptionViewModel option in facet.Options) 56 { 57 if (option.Selected) 58 { 59 selectedFacetsCount++; 60 } 61 } 62 } 63 } 64 } 65 } 66 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 67 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "none" ? " px-0 py-2" : contentPadding; 68 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " px-3 py-2" : contentPadding; 69 70 bool enableSorting = Model.Item.GetBoolean("SortByNameAZ"); 71 enableSorting = Model.Item.GetBoolean("SortByNameZA") || enableSorting == true ? true : false; 72 enableSorting = Model.Item.GetBoolean("SortByNewest") || enableSorting == true ? true : false; 73 enableSorting = Model.Item.GetBoolean("SortByLowestPrice") || enableSorting == true ? true : false; 74 enableSorting = Model.Item.GetBoolean("SortByHighestPrice") || enableSorting == true ? true : false; 75 76 string layout = Model.Item.GetRawValueString("Layout", "vertical"); 77 78 79 80 } 81 82 83 84 @if (productList.TotalProductsCount > 0 && (facetsFound || Model.Item.GetBoolean("EnableGroupNavigation") || enableSorting)) 85 { 86 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 87 string modalTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ModalTheme")) ? " theme " + Model.Item.GetRawValueString("ModalTheme").Replace(" ", "").Trim().ToLower() : ""; 88 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 89 string selectedFacetsLabel = selectedFacetsCount > 0 ? "(" + selectedFacetsCount + ")" : ""; 90 91 //Desktop 92 if (layout == "vertical") { 93 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-block h-100 @theme item_@Model.Item.SystemName.ToLower()"> 94 @RenderForm(productList, "desktop", enableSorting, layout) 95 </form> 96 97 <script> 98 99 function lastOpened (e){ 100 101 102 if (e.classList.contains('collapsed')){ 103 setCookie("LastOpenedFacet", 0, 0); 104 } else { 105 setCookie("LastOpenedFacet", e.innerText, 10); 106 } 107 108 109 } 110 111 function setCookie(name, value, maxAgeSeconds) { 112 var maxAgeSegment = "; max-age=" + maxAgeSeconds; 113 document.cookie = encodeURI(name) + "=" + encodeURI(value) + maxAgeSegment; 114 } 115 116 window.onscroll = function() {fixedFacets(facetsTopPosOriginal)}; 117 118 let facetsTopPosOriginal = document.getElementById("FacetsForm_Desktop_@Model.ID").getBoundingClientRect().top; 119 120 121 122 function fixedFacets(facetsTopPosOriginal){ 123 124 let scrollPosition = window.pageYOffset; 125 126 let headerBottomPos = document.getElementsByClassName("page-header")[0].getBoundingClientRect().bottom; 127 let footerTopPos = document.getElementsByClassName("page-footer")[0].getBoundingClientRect().top; 128 129 let facetsTop = document.getElementById("FacetsForm_Desktop_@Model.ID"); 130 let facetsTopPos = facetsTop.getBoundingClientRect().top; 131 let facetsBottomPos = facetsTop.getBoundingClientRect().bottom; 132 let facetsTopParent = facetsTop.parentElement; 133 134 let horizontalFacets; 135 let horizontalFacetsParent; 136 137 if (document.getElementsByClassName("sticky-facets-horizontal").length > 0 ){ 138 139 horizontalFacets = document.getElementsByClassName("sticky-facets-horizontal")[0]; 140 horizontalFacetsParent = document.getElementsByClassName("sticky-facets-horizontal")[0].parentElement; 141 142 } else { 143 144 horizontalFacets = document.getElementsByClassName("sticky-facets-horizontal-mobile")[0].parentElement; 145 horizontalFacetsParent = horizontalFacets.parentElement; 146 147 horizontalFacets.classList.add("sticky-mobile"); 148 149 } 150 151 152 if (facetsTopPosOriginal < scrollPosition + headerBottomPos ) { 153 facetsTop.classList.add("sticky"); 154 facetsTop.style.cssText = '--bs-columns:12; --sticky-top:' + headerBottomPos + 'px; width:' + facetsTopParent.offsetWidth + 'px'; 155 156 horizontalFacets.classList.add("sticky"); 157 horizontalFacets.style.cssText = '--sticky-top:' + headerBottomPos + 'px; width:' + horizontalFacetsParent.offsetWidth + 'px'; 158 159 160 } else { 161 facetsTop.classList.remove("sticky"); 162 horizontalFacets.classList.remove("sticky"); 163 } 164 } 165 166 </script> 167 168 } 169 if (layout == "horizontal") { 170 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " p-3" : contentPadding; 171 172 173 <div class="@theme @contentPadding h-100"> 174 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-flex gap-3 flex-row flex-wrap item_@Model.Item.SystemName.ToLower()"> 175 @RenderForm(productList, "desktop", enableSorting, layout) 176 177 @if (selectedFacetsCount > 0) { 178 <button type="button" class="btn btn-sm me-sm-1 me-lg-2" onclick="swift.ProductList.ResetFacets(event)"><span class="icon-2">@ReadFile(iconPath + "rotate-ccw.svg")</span> @Translate("Clear filters")</button> 179 } 180 </form> 181 </div> 182 } 183 184 bool showFiltersForThisGroup = false; 185 186 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 187 188 189 if (!string.IsNullOrEmpty(groupId)){ 190 191 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 192 193 194 foreach (var customfield in group.ProductGroupFieldValues) { 195 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 196 if (customfield.Value.ToString() == "True"){ 197 showFiltersForThisGroup = true; 198 } 199 } 200 201 } 202 } 203 204 205 if (showFiltersForThisGroup){ 206 207 208 //Mobile 209 <div class="d-block d-lg-none mt-lg-0 @(contentPadding)@(theme) sticky-facets-horizontal-mobile FacetsForm_Mobile_@Model.Item.SystemName.ToLower()_@Model.ID"> 210 211 212 213 <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#FacetsModal"> 214 <span class="d-flex align-items-center"> 215 <span class="flex-grow-1 text-start"> 216 @Translate("Filter") @selectedFacetsLabel 217 </span> 218 <span class="icon-2"> 219 @ReadFile(iconPath + "sliders.svg") 220 </span> 221 </span> 222 </button> 223 224 <form method="post" action="@url" data-response-target-element="content" class="modal" id="FacetsModal" tabindex="-1" aria-hidden="false"> 225 <div class="modal-dialog modal-fullscreen"> 226 <div class="modal-content"> 227 228 <div class="modal-header@(modalTheme)"> 229 <h5 class="modal-title">@Translate("Filters and sorting")</h5> 230 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="document.querySelector('body').style = ''"></button> 231 </div> 232 <div class="modal-body@(modalTheme)"> 233 @RenderForm(productList, "mobile", enableSorting) 234 </div> 235 <div class="modal-footer d-flex@(modalTheme)"> 236 @if (selectedFacetsCount != 0) 237 { 238 <button type="button" class="btn btn-secondary flex-fill" onclick="swift.ProductList.ResetFacets(event)">@Translate("Clear") (@selectedFacetsCount)</button> 239 } 240 <button type="button" class="btn btn-primary flex-fill" onclick="location.reload();">@Translate("Update")</button> 241 </div> 242 </div> 243 </div> 244 </form> 245 </div> 246 247 } 248 } 249 else 250 { 251 if (Pageview.IsVisualEditorMode) 252 { 253 <div class="alert alert-dark m-0" role="alert"> 254 <span>@Translate("Facets: The facets selectors will be shown here, if any")</span> 255 </div> 256 } 257 else if (productList.TotalProductsCount > 0) 258 { 259 @*<div class="alert alert-dark m-0" id="NoFiltersAlert_@Model.ID"> 260 @Translate("No filters are available") 261 </div>*@ 262 263 } 264 } 265 266 267 @helper RenderForm(ProductListViewModel productList, string deviceType, bool enableSorting, string layout = "vertical") 268 { 269 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 270 271 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 272 string pageSize = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("PageSize")) ? Dynamicweb.Context.Current.Request.QueryString.Get("PageSize") : productList.PageSize.ToString(); 273 274 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 275 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 276 277 string groupsTheme = ""; 278 string extraBottomMargin = ""; 279 if (deviceType != "mobile") 280 { 281 groupsTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("FacetGroupsTheme")) ? " theme " + Model.Item.GetRawValueString("FacetGroupsTheme").Replace(" ", "").Trim().ToLower() : ""; 282 extraBottomMargin = !string.IsNullOrEmpty(groupsTheme) ? "mb-3" : ""; 283 } 284 285 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 286 contentPadding = contentPadding == "none" ? " px-0 py-2" : contentPadding; 287 contentPadding = contentPadding == "small" ? " px-3 py-2" : contentPadding; 288 289 bool showFiltersForThisGroup = false; 290 291 292 if (!string.IsNullOrEmpty(groupId)){ 293 294 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 295 296 @*if (group.Id == "14.01"){ 297 showFiltersForThisGroup = true; 298 }*@ 299 300 301 foreach (var customfield in group.ProductGroupFieldValues) { 302 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 303 if (customfield.Value.ToString() == "True"){ 304 showFiltersForThisGroup = true; 305 } 306 } 307 308 } 309 310 311 @* if (group.ParentGroups.Count() > 0){ 312 foreach (var parentGroups in group.ParentGroups){ 313 if (parentGroups.Id == "14.01"){ 314 showFiltersForThisGroup = true; 315 } 316 if (parentGroups.Id == "14.02"){ 317 showFiltersForThisGroup = true; 318 } 319 if (parentGroups.Id == "14.03"){ 320 showFiltersForThisGroup = true; 321 } 322 323 if (parentGroups.ParentGroups.Count() > 0){ 324 foreach (var parentParentGroups in parentGroups.ParentGroups){ 325 326 if (parentParentGroups.Id == "14.01"){ 327 showFiltersForThisGroup = true; 328 } 329 330 } 331 } 332 333 } 334 } *@ 335 } 336 337 338 339 340 341 342 @*<input type="hidden" name="PageSize" value="@pageSize">*@ 343 344 345 if (!string.IsNullOrEmpty(searchQuery)) { 346 <input type="hidden" name="q" value="@searchQuery"> 347 <input type="hidden" name="SearchLayout" value="@searchLayout"> 348 } 349 350 351 if (Model.Item.GetBoolean("EnableGroupNavigation")) 352 { 353 int startLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStartLevel", "2")); 354 int stopLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStopLevel", "9")); 355 356 var navigationSettings = new NavigationSettings(); 357 navigationSettings.StartLevel = startLevel; 358 navigationSettings.StopLevel = stopLevel; 359 navigationSettings.Parameters.Add("ID", deviceType); 360 navigationSettings.Parameters.Add("HideTexts", false); 361 navigationSettings.Parameters.Add("HideIcons", true); 362 navigationSettings.Parameters.Add("ContentPadding", contentPadding); 363 navigationSettings.ExpandMode = ExpandMode.All; 364 365 if (layout == "vertical") { 366 <div class="border-bottom py-2@(@groupsTheme)"> 367 <div class="d-flex@(contentPadding)" data-bs-toggle="collapse" data-bs-target="#ProductGroupNavigation_@(deviceType)_@Model.ID" role="button" aria-expanded="true" aria-controls="ProductGroupNavigation_@(deviceType)_@Model.ID"> 368 <h2 class="opacity-85 m-0 flex-fill h6">@Translate("Navigation")</h2> 369 <div class="my-auto collapse-chevron-icon"></div> 370 </div> 371 <div class="collapse show" id="ProductGroupNavigation_@(deviceType)_@Model.ID"> 372 @Navigation.RenderNavigation("Navigation/Vertical.cshtml", navigationSettings) 373 </div> 374 </div> 375 } 376 377 } 378 379 380 int groupCount = 0; 381 int maxGroups = 999; 382 int totalGroups = productList?.FacetGroups != null ? productList.FacetGroups.Count() : 0; 383 384 var lastOpenedFacetCookie = HttpContext.Current.Request.Cookies["LastOpenedFacet"]; 385 386 387 if (productList.FacetGroups != null && showFiltersForThisGroup) { 388 <div class="facets-options"> 389 @if (showFiltersForThisGroup){ 390 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 391 { 392 string border = groupCount != totalGroups ? "border-bottom" : ""; 393 394 foreach (FacetViewModel facet in facetGroup.Facets) 395 { 396 string collapseClass = string.Empty; 397 string showClass = " show"; 398 string ariaExpanded = "true"; 399 var expandedFacetGroups = Model.Item.GetRawValueString("ExpandFacetGroups", "all"); 400 401 402 if (expandedFacetGroups != "all" && System.Text.RegularExpressions.Regex.IsMatch(expandedFacetGroups, "([0-9])")) 403 { 404 if (groupCount >= Dynamicweb.Core.Converter.ToInt32(expandedFacetGroups)) 405 { 406 collapseClass = " collapsed"; 407 showClass = string.Empty; 408 ariaExpanded = "false"; 409 } 410 411 } 412 413 if(lastOpenedFacetCookie != null){ 414 if (Translate(facet.Name) == lastOpenedFacetCookie.Value.Replace("%20", " ")){ 415 collapseClass = string.Empty; 416 showClass = " show"; 417 ariaExpanded = "true"; 418 } 419 420 } 421 422 if (facet.Options.Count() > 0) 423 { 424 if (layout == "vertical") { 425 <div class="@border@(contentPadding)@(@groupsTheme)"> 426 <div class="d-flex@(collapseClass)" data-bs-toggle="collapse" data-bs-target="#FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID" role="button" aria-expanded="@ariaExpanded" aria-controls="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID" onclick="lastOpened(this)"> 427 <h2 class="opacity-85 m-0 flex-fill h6 my-2">@Translate(facet.Name)</h2> 428 <div class="my-auto collapse-chevron-icon"></div> 429 </div> 430 <div class="collapse@(showClass)" id="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID"> 431 @foreach (FacetOptionViewModel facetOption in facet.Options) 432 { 433 string renderType = facet.RenderType; 434 435 if (renderType == "Colors") 436 { 437 @RenderColorOption(facet, facetOption) 438 } 439 else 440 { 441 @RenderCheckboxOption(facet, facetOption) 442 } 443 } 444 </div> 445 </div> 446 } 447 if (layout == "horizontal") { 448 string hideSelector = groupCount < maxGroups ? "" : "d-none"; 449 int selectedFacetsInGroup = 0; 450 451 foreach (FacetOptionViewModel option in facet.Options) 452 { 453 if (option.Selected) 454 { 455 selectedFacetsInGroup++; 456 } 457 } 458 459 string label = selectedFacetsInGroup > 0 ? @Translate(facet.Name) + "<span class=\"badge bg-dark opacity-50 text-white ms-2\">" + selectedFacetsInGroup + "</span>" : @Translate(facet.Name); 460 461 <div class="dropdown @hideSelector js-facets-selector"> 462 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 463 @label 464 </button> 465 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" style="min-width: 280px"> 466 @foreach (FacetOptionViewModel facetOption in facet.Options) 467 { 468 string translation = Translate(facetOption?.Value.ToString()); // 469 string renderType = facet.RenderType; 470 471 if (renderType == "Colors") 472 { 473 @RenderColorOption(facet, facetOption) 474 } 475 else 476 { 477 @RenderCheckboxOption(facet, facetOption) 478 } 479 } 480 </div> 481 </div> 482 } 483 484 groupCount++; 485 } 486 } 487 } 488 } 489 490 </div> 491 } 492 493 if (enableSorting) 494 { 495 <div class="right"> 496 @if (layout == "vertical") { 497 <div class="border-bottom@(contentPadding)@(groupsTheme)"> 498 <h2 class="opacity-85 m-0 my-2 flex-fill h6">@Translate("Sort by")</h2> 499 <div class="d-flex flex-column gap-2" id="SortBy_@(deviceType)_@Model.ID"> 500 @RenderSorting(deviceType) 501 </div> 502 </div> 503 } 504 @if (layout == "horizontal") { 505 506 <button class="btn @(groupsTheme) dropdown-toggle sort-button" type="button" id="SortBy_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 507 @Translate("Sort by") 508 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><g data-name="81-Arrow Exchange"><path d="m16.71 7.29-7-7a1 1 0 0 0-1.41 0l-7 7 1.41 1.42L8 3.41V32h2V3.41l5.29 5.29zM29.29 23.29 24 28.59V0h-2v28.59l-5.29-5.29-1.41 1.41 7 7a1 1 0 0 0 1.41 0l7-7z"/></g></svg> 509 </button> 510 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="SortBy_@(deviceType)_@Model.ID" style="min-width: 280px"> 511 <div class="d-flex flex-column gap-2"> 512 @RenderSorting(deviceType) 513 </div> 514 </div> 515 } 516 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="PageSize_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 517 @Translate("Show product per page") 518 </button> 519 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="PageSize_@Model.ID" style="min-width: 280px"> 520 <div class="d-flex flex-column gap-2"> 521 @RenderChoosePageSize(pageSize) 522 </div> 523 </div> 524 </div> 525 } 526 527 528 if ((groupCount > maxGroups) && layout == "horizontal") { 529 <button type="button" class="btn @(groupsTheme)" onclick="this.closest('form').querySelectorAll('.js-facets-selector').forEach(function (selector) { selector.classList.remove('d-none'); }); this.classList.add('d-none');"><span class="icon-2">@ReadFile(iconPath + "sliders.svg")</span> @Translate("All filters")</button> 530 } 531 } 532 533 @helper RenderChoosePageSize(string pageSize ){ 534 535 //int originalPageSize = Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) > 0 ? Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) : 12; 536 537 538 <div class="form-check"> 539 <input @if (pageSize == "12") { <text> checked="checked" </text> } 540 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="12" id="PageSize_12_@Model.ID"> 541 <label class="form-check-label" for="PageSize_12_@Model.ID"> 542 12 543 </label> 544 </div> 545 <div class="form-check"> 546 <input @if (pageSize == "24") { <text> checked="checked" </text> } 547 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="24" id="PageSize_24_@Model.ID"> 548 <label class="form-check-label" for="PageSize_24_@Model.ID"> 549 24 550 </label> 551 </div> 552 <div class="form-check"> 553 <input @if (pageSize == "48") { <text> checked="checked" </text> } 554 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="48" id="PageSize_48_@Model.ID"> 555 <label class="form-check-label" for="PageSize_48_@Model.ID"> 556 48 557 </label> 558 </div> 559 <div class="form-check"> 560 <input @if (pageSize == "96") { <text> checked="checked" </text> } 561 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="96" id="PageSize_96_@Model.ID"> 562 <label class="form-check-label" for="PageSize_96_@Model.ID"> 563 96 564 </label> 565 </div> 566 } 567 568 @helper RenderSorting(string deviceType) { 569 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 570 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 571 string sortNameSelectedRelevance = sortBySelection.ToLower() == "" || sortBySelection.ToLower() == "relevance" ? "checked" : ""; 572 string sortNameSelectedAZ = sortBySelection.ToLower() == "nameforsort" ? "checked" : ""; 573 string sortNameSelectedZA = sortBySelection.ToLower() == "-nameforsort" ? "checked" : ""; 574 string sortPriceLowSelected = sortBySelection.ToLower() == "price" ? "checked" : ""; 575 string sortPriceHighSelected = sortBySelection.ToLower() == "-price" ? "checked" : ""; 576 string sortNewSelected = sortBySelection.ToLower() == "-created" ? "checked" : ""; 577 string sortMostSoldSelected = sortBySelection.ToLower() == "-ordercount" ? "checked" : ""; 578 579 string sortProductNr = sortBySelection.ToLower() == "productnumbersort" ? "checked" : ""; 580 string sortProductNrZA = sortBySelection.ToLower() == "-productnumbersort" ? "checked" : ""; 581 582 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 583 bool anonymousUser = Pageview.User == null; 584 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 585 586 if (Model.Item.GetBoolean("SortByRelevance")) 587 { 588 <div class="form-check"> 589 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="" id="SortByRelevance_@(deviceType)_@Model.ID" @sortNameSelectedRelevance> 590 <label class="form-check-label" for="SortByRelevance_@(deviceType)_@Model.ID"> 591 @Translate("Relevance") 592 </label> 593 </div> 594 } 595 if (Model.Item.GetBoolean("SortByNameAZ")) 596 { 597 <div class="form-check"> 598 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="NameForSort" id="SortByNameAZ_@(deviceType)_@Model.ID" @sortNameSelectedAZ> 599 <label class="form-check-label" for="SortByNameAZ_@(deviceType)_@Model.ID"> 600 @Translate("Name (A-Z)") 601 </label> 602 </div> 603 } 604 if (Model.Item.GetBoolean("SortByNameZA")) 605 { 606 <div class="form-check"> 607 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-NameForSort" id="SortByNameZA_@(deviceType)_@Model.ID" @sortNameSelectedZA> 608 <label class="form-check-label" for="SortByNameZA_@(deviceType)_@Model.ID"> 609 @Translate("Name (Z-A)") 610 </label> 611 </div> 612 } 613 if (Model.Item.GetBoolean("SortByNewest")) 614 { 615 <div class="form-check"> 616 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-created" id="SortByNew_@(deviceType)_@Model.ID" @sortNewSelected> 617 <label class="form-check-label" for="SortByNew_@(deviceType)_@Model.ID"> 618 @Translate("Newest") 619 </label> 620 </div> 621 } 622 if (!hidePrice) 623 { 624 if (Model.Item.GetBoolean("SortByLowestPrice")) 625 { 626 <div class="form-check"> 627 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="Price" id="SortByPriceLow_@(deviceType)_@Model.ID" @sortPriceLowSelected> 628 <label class="form-check-label" for="SortByPriceLow_@(deviceType)_@Model.ID"> 629 @Translate("Lowest price") 630 </label> 631 </div> 632 } 633 if (Model.Item.GetBoolean("SortByHighestPrice")) 634 { 635 <div class="form-check"> 636 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-Price" id="SortByPriceHigh_@(deviceType)_@Model.ID" @sortPriceHighSelected> 637 <label class="form-check-label" for="SortByPriceHigh_@(deviceType)_@Model.ID"> 638 @Translate("Highest price") 639 </label> 640 </div> 641 } 642 } 643 if (Model.Item.GetBoolean("SortByMostSold")) 644 { 645 <div class="form-check"> 646 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-OrderCount" id="SortByMostSold_@(deviceType)_@Model.ID" @sortMostSoldSelected> 647 <label class="form-check-label" for="SortByMostSold_@(deviceType)_@Model.ID"> 648 @Translate("Most sold") 649 </label> 650 </div> 651 } 652 <div class="form-check"> 653 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="ProductNumberSort" id="ProductNumberSort_@(deviceType)_@Model.ID" @sortProductNr> 654 <label class="form-check-label" for="ProductNumberSort_@(deviceType)_@Model.ID"> 655 @Translate("Product No. (Low)") 656 </label> 657 </div> 658 659 <div class="form-check"> 660 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-ProductNumberSort" id="ProductNumberSortZA_@(deviceType)_@Model.ID" @sortProductNrZA> 661 <label class="form-check-label" for="ProductNumberSortZA_@(deviceType)_@Model.ID"> 662 @Translate("Product No. (High)") 663 </label> 664 </div> 665 } 666 667 @helper RenderCheckboxOption(FacetViewModel facet, FacetOptionViewModel facetOption) 668 { 669 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 670 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 671 string selected = facetOption.Selected ? "checked" : ""; 672 673 if (facetLabel.ToLower() == "true") 674 { 675 facetLabel = Translate("Yes"); 676 } 677 678 if (facetLabel.ToLower() == "false") 679 { 680 facetLabel = Translate("No"); 681 } 682 683 <label class="form-check mt-1" @disabled> 684 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="form-check-input" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected> 685 <span class="form-check-label d-flex align-items-center"> 686 <span class="flex-fill">@Translate(facetLabel) </span> 687 @if (facet.FacetType.ToLower() == "field") { 688 <small class="opacity-85">@facetOption.Count</small> 689 } 690 </span> 691 </label> 692 } 693 694 @helper RenderColorOption(FacetViewModel facet, FacetOptionViewModel facetOption) 695 { 696 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 697 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 698 string selected = facetOption.Selected ? "checked" : ""; 699 700 string image = facetOption.Value; 701 string colorCode = facetOption.Value; 702 703 var variantOption = Dynamicweb.Ecommerce.Services.VariantOptions.GetVariantOption(facetOption.Value.ToString(), Dynamicweb.Ecommerce.Common.Context.LanguageID); 704 if (variantOption != null) 705 { 706 image = variantOption.LargeImage; 707 colorCode = variantOption.Color; 708 } 709 710 <div class="colorbox"> 711 <label> 712 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="@disabled @selected" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected title="@facetOption.Label"> 713 @if (colorCode.Contains("#")) 714 { 715 <span class="colorbox-background" style="background-color: @colorCode"></span> 716 <span class="visually-hidden">@Translate(facetOption.Label)</span> 717 } 718 else 719 { 720 <img class="colorbox-background" src="/Admin/Public/GetImage.ashx?width=25&height=25&image=@image"> 721 <span class="visually-hidden">@Translate(facetOption.Label)</span> 722 } 723 </label> 724 </div> 725 } 726 727
Error executing template "Designs/Swift/Paragraph/Swift_ProductListFacets.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_7f4593ab194c4b09ac0b50f1df395543.<>c__DisplayClass0_0.<RenderForm>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 301 at CompiledRazorTemplates.Dynamic.RazorEngine_7f4593ab194c4b09ac0b50f1df395543.Execute() in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 175 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.Ecommerce.ProductCatalog 3 @using Dynamicweb.Frontend.Navigation 4 @using Dynamicweb.Environment 5 @using Dynamicweb.Core.Encoders 6 @using System.Web 7 @using Dynamicweb.Core 8 @using System.Linq 9 10 @{ 11 ProductListViewModel productList = new ProductListViewModel(); 12 13 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 14 { 15 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 16 } 17 18 string url = Pageview.SearchFriendlyUrl; 19 20 21 url = url.LastIndexOf("?") != -1 ? url.Substring(0, url.LastIndexOf("?")) : url; 22 23 24 25 //Fix for non-friendly urls 26 if (Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") != null) 27 { 28 string groupId = Dynamicweb.Context.Current.Request.QueryString.Get("GroupID"); 29 url += "?GroupID=" + groupId; 30 31 32 } 33 34 35 if (!url.Contains("LayoutTemplate")) 36 { 37 url += url.Contains("?") ? "&LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml" : "?LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml"; 38 } 39 40 bool facetsFound = false; 41 int selectedFacetsCount = 0; 42 43 44 45 if (productList.FacetGroups != null) 46 { 47 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 48 { 49 foreach (FacetViewModel facet in facetGroup.Facets) 50 { 51 if (facet.Options.Count() > 0) 52 { 53 facetsFound = true; 54 55 foreach (FacetOptionViewModel option in facet.Options) 56 { 57 if (option.Selected) 58 { 59 selectedFacetsCount++; 60 } 61 } 62 } 63 } 64 } 65 } 66 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 67 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "none" ? " px-0 py-2" : contentPadding; 68 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " px-3 py-2" : contentPadding; 69 70 bool enableSorting = Model.Item.GetBoolean("SortByNameAZ"); 71 enableSorting = Model.Item.GetBoolean("SortByNameZA") || enableSorting == true ? true : false; 72 enableSorting = Model.Item.GetBoolean("SortByNewest") || enableSorting == true ? true : false; 73 enableSorting = Model.Item.GetBoolean("SortByLowestPrice") || enableSorting == true ? true : false; 74 enableSorting = Model.Item.GetBoolean("SortByHighestPrice") || enableSorting == true ? true : false; 75 76 string layout = Model.Item.GetRawValueString("Layout", "vertical"); 77 78 79 80 } 81 82 83 84 @if (productList.TotalProductsCount > 0 && (facetsFound || Model.Item.GetBoolean("EnableGroupNavigation") || enableSorting)) 85 { 86 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 87 string modalTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ModalTheme")) ? " theme " + Model.Item.GetRawValueString("ModalTheme").Replace(" ", "").Trim().ToLower() : ""; 88 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 89 string selectedFacetsLabel = selectedFacetsCount > 0 ? "(" + selectedFacetsCount + ")" : ""; 90 91 //Desktop 92 if (layout == "vertical") { 93 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-block h-100 @theme item_@Model.Item.SystemName.ToLower()"> 94 @RenderForm(productList, "desktop", enableSorting, layout) 95 </form> 96 97 <script> 98 99 function lastOpened (e){ 100 101 102 if (e.classList.contains('collapsed')){ 103 setCookie("LastOpenedFacet", 0, 0); 104 } else { 105 setCookie("LastOpenedFacet", e.innerText, 10); 106 } 107 108 109 } 110 111 function setCookie(name, value, maxAgeSeconds) { 112 var maxAgeSegment = "; max-age=" + maxAgeSeconds; 113 document.cookie = encodeURI(name) + "=" + encodeURI(value) + maxAgeSegment; 114 } 115 116 window.onscroll = function() {fixedFacets(facetsTopPosOriginal)}; 117 118 let facetsTopPosOriginal = document.getElementById("FacetsForm_Desktop_@Model.ID").getBoundingClientRect().top; 119 120 121 122 function fixedFacets(facetsTopPosOriginal){ 123 124 let scrollPosition = window.pageYOffset; 125 126 let headerBottomPos = document.getElementsByClassName("page-header")[0].getBoundingClientRect().bottom; 127 let footerTopPos = document.getElementsByClassName("page-footer")[0].getBoundingClientRect().top; 128 129 let facetsTop = document.getElementById("FacetsForm_Desktop_@Model.ID"); 130 let facetsTopPos = facetsTop.getBoundingClientRect().top; 131 let facetsBottomPos = facetsTop.getBoundingClientRect().bottom; 132 let facetsTopParent = facetsTop.parentElement; 133 134 let horizontalFacets; 135 let horizontalFacetsParent; 136 137 if (document.getElementsByClassName("sticky-facets-horizontal").length > 0 ){ 138 139 horizontalFacets = document.getElementsByClassName("sticky-facets-horizontal")[0]; 140 horizontalFacetsParent = document.getElementsByClassName("sticky-facets-horizontal")[0].parentElement; 141 142 } else { 143 144 horizontalFacets = document.getElementsByClassName("sticky-facets-horizontal-mobile")[0].parentElement; 145 horizontalFacetsParent = horizontalFacets.parentElement; 146 147 horizontalFacets.classList.add("sticky-mobile"); 148 149 } 150 151 152 if (facetsTopPosOriginal < scrollPosition + headerBottomPos ) { 153 facetsTop.classList.add("sticky"); 154 facetsTop.style.cssText = '--bs-columns:12; --sticky-top:' + headerBottomPos + 'px; width:' + facetsTopParent.offsetWidth + 'px'; 155 156 horizontalFacets.classList.add("sticky"); 157 horizontalFacets.style.cssText = '--sticky-top:' + headerBottomPos + 'px; width:' + horizontalFacetsParent.offsetWidth + 'px'; 158 159 160 } else { 161 facetsTop.classList.remove("sticky"); 162 horizontalFacets.classList.remove("sticky"); 163 } 164 } 165 166 </script> 167 168 } 169 if (layout == "horizontal") { 170 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " p-3" : contentPadding; 171 172 173 <div class="@theme @contentPadding h-100"> 174 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-flex gap-3 flex-row flex-wrap item_@Model.Item.SystemName.ToLower()"> 175 @RenderForm(productList, "desktop", enableSorting, layout) 176 177 @if (selectedFacetsCount > 0) { 178 <button type="button" class="btn btn-sm me-sm-1 me-lg-2" onclick="swift.ProductList.ResetFacets(event)"><span class="icon-2">@ReadFile(iconPath + "rotate-ccw.svg")</span> @Translate("Clear filters")</button> 179 } 180 </form> 181 </div> 182 } 183 184 bool showFiltersForThisGroup = false; 185 186 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 187 188 189 if (!string.IsNullOrEmpty(groupId)){ 190 191 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 192 193 194 foreach (var customfield in group.ProductGroupFieldValues) { 195 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 196 if (customfield.Value.ToString() == "True"){ 197 showFiltersForThisGroup = true; 198 } 199 } 200 201 } 202 } 203 204 205 if (showFiltersForThisGroup){ 206 207 208 //Mobile 209 <div class="d-block d-lg-none mt-lg-0 @(contentPadding)@(theme) sticky-facets-horizontal-mobile FacetsForm_Mobile_@Model.Item.SystemName.ToLower()_@Model.ID"> 210 211 212 213 <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#FacetsModal"> 214 <span class="d-flex align-items-center"> 215 <span class="flex-grow-1 text-start"> 216 @Translate("Filter") @selectedFacetsLabel 217 </span> 218 <span class="icon-2"> 219 @ReadFile(iconPath + "sliders.svg") 220 </span> 221 </span> 222 </button> 223 224 <form method="post" action="@url" data-response-target-element="content" class="modal" id="FacetsModal" tabindex="-1" aria-hidden="false"> 225 <div class="modal-dialog modal-fullscreen"> 226 <div class="modal-content"> 227 228 <div class="modal-header@(modalTheme)"> 229 <h5 class="modal-title">@Translate("Filters and sorting")</h5> 230 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="document.querySelector('body').style = ''"></button> 231 </div> 232 <div class="modal-body@(modalTheme)"> 233 @RenderForm(productList, "mobile", enableSorting) 234 </div> 235 <div class="modal-footer d-flex@(modalTheme)"> 236 @if (selectedFacetsCount != 0) 237 { 238 <button type="button" class="btn btn-secondary flex-fill" onclick="swift.ProductList.ResetFacets(event)">@Translate("Clear") (@selectedFacetsCount)</button> 239 } 240 <button type="button" class="btn btn-primary flex-fill" onclick="location.reload();">@Translate("Update")</button> 241 </div> 242 </div> 243 </div> 244 </form> 245 </div> 246 247 } 248 } 249 else 250 { 251 if (Pageview.IsVisualEditorMode) 252 { 253 <div class="alert alert-dark m-0" role="alert"> 254 <span>@Translate("Facets: The facets selectors will be shown here, if any")</span> 255 </div> 256 } 257 else if (productList.TotalProductsCount > 0) 258 { 259 @*<div class="alert alert-dark m-0" id="NoFiltersAlert_@Model.ID"> 260 @Translate("No filters are available") 261 </div>*@ 262 263 } 264 } 265 266 267 @helper RenderForm(ProductListViewModel productList, string deviceType, bool enableSorting, string layout = "vertical") 268 { 269 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 270 271 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 272 string pageSize = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("PageSize")) ? Dynamicweb.Context.Current.Request.QueryString.Get("PageSize") : productList.PageSize.ToString(); 273 274 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 275 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 276 277 string groupsTheme = ""; 278 string extraBottomMargin = ""; 279 if (deviceType != "mobile") 280 { 281 groupsTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("FacetGroupsTheme")) ? " theme " + Model.Item.GetRawValueString("FacetGroupsTheme").Replace(" ", "").Trim().ToLower() : ""; 282 extraBottomMargin = !string.IsNullOrEmpty(groupsTheme) ? "mb-3" : ""; 283 } 284 285 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 286 contentPadding = contentPadding == "none" ? " px-0 py-2" : contentPadding; 287 contentPadding = contentPadding == "small" ? " px-3 py-2" : contentPadding; 288 289 bool showFiltersForThisGroup = false; 290 291 292 if (!string.IsNullOrEmpty(groupId)){ 293 294 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 295 296 @*if (group.Id == "14.01"){ 297 showFiltersForThisGroup = true; 298 }*@ 299 300 301 foreach (var customfield in group.ProductGroupFieldValues) { 302 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 303 if (customfield.Value.ToString() == "True"){ 304 showFiltersForThisGroup = true; 305 } 306 } 307 308 } 309 310 311 @* if (group.ParentGroups.Count() > 0){ 312 foreach (var parentGroups in group.ParentGroups){ 313 if (parentGroups.Id == "14.01"){ 314 showFiltersForThisGroup = true; 315 } 316 if (parentGroups.Id == "14.02"){ 317 showFiltersForThisGroup = true; 318 } 319 if (parentGroups.Id == "14.03"){ 320 showFiltersForThisGroup = true; 321 } 322 323 if (parentGroups.ParentGroups.Count() > 0){ 324 foreach (var parentParentGroups in parentGroups.ParentGroups){ 325 326 if (parentParentGroups.Id == "14.01"){ 327 showFiltersForThisGroup = true; 328 } 329 330 } 331 } 332 333 } 334 } *@ 335 } 336 337 338 339 340 341 342 @*<input type="hidden" name="PageSize" value="@pageSize">*@ 343 344 345 if (!string.IsNullOrEmpty(searchQuery)) { 346 <input type="hidden" name="q" value="@searchQuery"> 347 <input type="hidden" name="SearchLayout" value="@searchLayout"> 348 } 349 350 351 if (Model.Item.GetBoolean("EnableGroupNavigation")) 352 { 353 int startLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStartLevel", "2")); 354 int stopLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStopLevel", "9")); 355 356 var navigationSettings = new NavigationSettings(); 357 navigationSettings.StartLevel = startLevel; 358 navigationSettings.StopLevel = stopLevel; 359 navigationSettings.Parameters.Add("ID", deviceType); 360 navigationSettings.Parameters.Add("HideTexts", false); 361 navigationSettings.Parameters.Add("HideIcons", true); 362 navigationSettings.Parameters.Add("ContentPadding", contentPadding); 363 navigationSettings.ExpandMode = ExpandMode.All; 364 365 if (layout == "vertical") { 366 <div class="border-bottom py-2@(@groupsTheme)"> 367 <div class="d-flex@(contentPadding)" data-bs-toggle="collapse" data-bs-target="#ProductGroupNavigation_@(deviceType)_@Model.ID" role="button" aria-expanded="true" aria-controls="ProductGroupNavigation_@(deviceType)_@Model.ID"> 368 <h2 class="opacity-85 m-0 flex-fill h6">@Translate("Navigation")</h2> 369 <div class="my-auto collapse-chevron-icon"></div> 370 </div> 371 <div class="collapse show" id="ProductGroupNavigation_@(deviceType)_@Model.ID"> 372 @Navigation.RenderNavigation("Navigation/Vertical.cshtml", navigationSettings) 373 </div> 374 </div> 375 } 376 377 } 378 379 380 int groupCount = 0; 381 int maxGroups = 999; 382 int totalGroups = productList?.FacetGroups != null ? productList.FacetGroups.Count() : 0; 383 384 var lastOpenedFacetCookie = HttpContext.Current.Request.Cookies["LastOpenedFacet"]; 385 386 387 if (productList.FacetGroups != null && showFiltersForThisGroup) { 388 <div class="facets-options"> 389 @if (showFiltersForThisGroup){ 390 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 391 { 392 string border = groupCount != totalGroups ? "border-bottom" : ""; 393 394 foreach (FacetViewModel facet in facetGroup.Facets) 395 { 396 string collapseClass = string.Empty; 397 string showClass = " show"; 398 string ariaExpanded = "true"; 399 var expandedFacetGroups = Model.Item.GetRawValueString("ExpandFacetGroups", "all"); 400 401 402 if (expandedFacetGroups != "all" && System.Text.RegularExpressions.Regex.IsMatch(expandedFacetGroups, "([0-9])")) 403 { 404 if (groupCount >= Dynamicweb.Core.Converter.ToInt32(expandedFacetGroups)) 405 { 406 collapseClass = " collapsed"; 407 showClass = string.Empty; 408 ariaExpanded = "false"; 409 } 410 411 } 412 413 if(lastOpenedFacetCookie != null){ 414 if (Translate(facet.Name) == lastOpenedFacetCookie.Value.Replace("%20", " ")){ 415 collapseClass = string.Empty; 416 showClass = " show"; 417 ariaExpanded = "true"; 418 } 419 420 } 421 422 if (facet.Options.Count() > 0) 423 { 424 if (layout == "vertical") { 425 <div class="@border@(contentPadding)@(@groupsTheme)"> 426 <div class="d-flex@(collapseClass)" data-bs-toggle="collapse" data-bs-target="#FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID" role="button" aria-expanded="@ariaExpanded" aria-controls="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID" onclick="lastOpened(this)"> 427 <h2 class="opacity-85 m-0 flex-fill h6 my-2">@Translate(facet.Name)</h2> 428 <div class="my-auto collapse-chevron-icon"></div> 429 </div> 430 <div class="collapse@(showClass)" id="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID"> 431 @foreach (FacetOptionViewModel facetOption in facet.Options) 432 { 433 string renderType = facet.RenderType; 434 435 if (renderType == "Colors") 436 { 437 @RenderColorOption(facet, facetOption) 438 } 439 else 440 { 441 @RenderCheckboxOption(facet, facetOption) 442 } 443 } 444 </div> 445 </div> 446 } 447 if (layout == "horizontal") { 448 string hideSelector = groupCount < maxGroups ? "" : "d-none"; 449 int selectedFacetsInGroup = 0; 450 451 foreach (FacetOptionViewModel option in facet.Options) 452 { 453 if (option.Selected) 454 { 455 selectedFacetsInGroup++; 456 } 457 } 458 459 string label = selectedFacetsInGroup > 0 ? @Translate(facet.Name) + "<span class=\"badge bg-dark opacity-50 text-white ms-2\">" + selectedFacetsInGroup + "</span>" : @Translate(facet.Name); 460 461 <div class="dropdown @hideSelector js-facets-selector"> 462 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 463 @label 464 </button> 465 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" style="min-width: 280px"> 466 @foreach (FacetOptionViewModel facetOption in facet.Options) 467 { 468 string translation = Translate(facetOption?.Value.ToString()); // 469 string renderType = facet.RenderType; 470 471 if (renderType == "Colors") 472 { 473 @RenderColorOption(facet, facetOption) 474 } 475 else 476 { 477 @RenderCheckboxOption(facet, facetOption) 478 } 479 } 480 </div> 481 </div> 482 } 483 484 groupCount++; 485 } 486 } 487 } 488 } 489 490 </div> 491 } 492 493 if (enableSorting) 494 { 495 <div class="right"> 496 @if (layout == "vertical") { 497 <div class="border-bottom@(contentPadding)@(groupsTheme)"> 498 <h2 class="opacity-85 m-0 my-2 flex-fill h6">@Translate("Sort by")</h2> 499 <div class="d-flex flex-column gap-2" id="SortBy_@(deviceType)_@Model.ID"> 500 @RenderSorting(deviceType) 501 </div> 502 </div> 503 } 504 @if (layout == "horizontal") { 505 506 <button class="btn @(groupsTheme) dropdown-toggle sort-button" type="button" id="SortBy_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 507 @Translate("Sort by") 508 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><g data-name="81-Arrow Exchange"><path d="m16.71 7.29-7-7a1 1 0 0 0-1.41 0l-7 7 1.41 1.42L8 3.41V32h2V3.41l5.29 5.29zM29.29 23.29 24 28.59V0h-2v28.59l-5.29-5.29-1.41 1.41 7 7a1 1 0 0 0 1.41 0l7-7z"/></g></svg> 509 </button> 510 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="SortBy_@(deviceType)_@Model.ID" style="min-width: 280px"> 511 <div class="d-flex flex-column gap-2"> 512 @RenderSorting(deviceType) 513 </div> 514 </div> 515 } 516 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="PageSize_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 517 @Translate("Show product per page") 518 </button> 519 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="PageSize_@Model.ID" style="min-width: 280px"> 520 <div class="d-flex flex-column gap-2"> 521 @RenderChoosePageSize(pageSize) 522 </div> 523 </div> 524 </div> 525 } 526 527 528 if ((groupCount > maxGroups) && layout == "horizontal") { 529 <button type="button" class="btn @(groupsTheme)" onclick="this.closest('form').querySelectorAll('.js-facets-selector').forEach(function (selector) { selector.classList.remove('d-none'); }); this.classList.add('d-none');"><span class="icon-2">@ReadFile(iconPath + "sliders.svg")</span> @Translate("All filters")</button> 530 } 531 } 532 533 @helper RenderChoosePageSize(string pageSize ){ 534 535 //int originalPageSize = Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) > 0 ? Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) : 12; 536 537 538 <div class="form-check"> 539 <input @if (pageSize == "12") { <text> checked="checked" </text> } 540 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="12" id="PageSize_12_@Model.ID"> 541 <label class="form-check-label" for="PageSize_12_@Model.ID"> 542 12 543 </label> 544 </div> 545 <div class="form-check"> 546 <input @if (pageSize == "24") { <text> checked="checked" </text> } 547 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="24" id="PageSize_24_@Model.ID"> 548 <label class="form-check-label" for="PageSize_24_@Model.ID"> 549 24 550 </label> 551 </div> 552 <div class="form-check"> 553 <input @if (pageSize == "48") { <text> checked="checked" </text> } 554 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="48" id="PageSize_48_@Model.ID"> 555 <label class="form-check-label" for="PageSize_48_@Model.ID"> 556 48 557 </label> 558 </div> 559 <div class="form-check"> 560 <input @if (pageSize == "96") { <text> checked="checked" </text> } 561 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="96" id="PageSize_96_@Model.ID"> 562 <label class="form-check-label" for="PageSize_96_@Model.ID"> 563 96 564 </label> 565 </div> 566 } 567 568 @helper RenderSorting(string deviceType) { 569 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 570 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 571 string sortNameSelectedRelevance = sortBySelection.ToLower() == "" || sortBySelection.ToLower() == "relevance" ? "checked" : ""; 572 string sortNameSelectedAZ = sortBySelection.ToLower() == "nameforsort" ? "checked" : ""; 573 string sortNameSelectedZA = sortBySelection.ToLower() == "-nameforsort" ? "checked" : ""; 574 string sortPriceLowSelected = sortBySelection.ToLower() == "price" ? "checked" : ""; 575 string sortPriceHighSelected = sortBySelection.ToLower() == "-price" ? "checked" : ""; 576 string sortNewSelected = sortBySelection.ToLower() == "-created" ? "checked" : ""; 577 string sortMostSoldSelected = sortBySelection.ToLower() == "-ordercount" ? "checked" : ""; 578 579 string sortProductNr = sortBySelection.ToLower() == "productnumbersort" ? "checked" : ""; 580 string sortProductNrZA = sortBySelection.ToLower() == "-productnumbersort" ? "checked" : ""; 581 582 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 583 bool anonymousUser = Pageview.User == null; 584 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 585 586 if (Model.Item.GetBoolean("SortByRelevance")) 587 { 588 <div class="form-check"> 589 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="" id="SortByRelevance_@(deviceType)_@Model.ID" @sortNameSelectedRelevance> 590 <label class="form-check-label" for="SortByRelevance_@(deviceType)_@Model.ID"> 591 @Translate("Relevance") 592 </label> 593 </div> 594 } 595 if (Model.Item.GetBoolean("SortByNameAZ")) 596 { 597 <div class="form-check"> 598 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="NameForSort" id="SortByNameAZ_@(deviceType)_@Model.ID" @sortNameSelectedAZ> 599 <label class="form-check-label" for="SortByNameAZ_@(deviceType)_@Model.ID"> 600 @Translate("Name (A-Z)") 601 </label> 602 </div> 603 } 604 if (Model.Item.GetBoolean("SortByNameZA")) 605 { 606 <div class="form-check"> 607 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-NameForSort" id="SortByNameZA_@(deviceType)_@Model.ID" @sortNameSelectedZA> 608 <label class="form-check-label" for="SortByNameZA_@(deviceType)_@Model.ID"> 609 @Translate("Name (Z-A)") 610 </label> 611 </div> 612 } 613 if (Model.Item.GetBoolean("SortByNewest")) 614 { 615 <div class="form-check"> 616 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-created" id="SortByNew_@(deviceType)_@Model.ID" @sortNewSelected> 617 <label class="form-check-label" for="SortByNew_@(deviceType)_@Model.ID"> 618 @Translate("Newest") 619 </label> 620 </div> 621 } 622 if (!hidePrice) 623 { 624 if (Model.Item.GetBoolean("SortByLowestPrice")) 625 { 626 <div class="form-check"> 627 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="Price" id="SortByPriceLow_@(deviceType)_@Model.ID" @sortPriceLowSelected> 628 <label class="form-check-label" for="SortByPriceLow_@(deviceType)_@Model.ID"> 629 @Translate("Lowest price") 630 </label> 631 </div> 632 } 633 if (Model.Item.GetBoolean("SortByHighestPrice")) 634 { 635 <div class="form-check"> 636 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-Price" id="SortByPriceHigh_@(deviceType)_@Model.ID" @sortPriceHighSelected> 637 <label class="form-check-label" for="SortByPriceHigh_@(deviceType)_@Model.ID"> 638 @Translate("Highest price") 639 </label> 640 </div> 641 } 642 } 643 if (Model.Item.GetBoolean("SortByMostSold")) 644 { 645 <div class="form-check"> 646 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-OrderCount" id="SortByMostSold_@(deviceType)_@Model.ID" @sortMostSoldSelected> 647 <label class="form-check-label" for="SortByMostSold_@(deviceType)_@Model.ID"> 648 @Translate("Most sold") 649 </label> 650 </div> 651 } 652 <div class="form-check"> 653 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="ProductNumberSort" id="ProductNumberSort_@(deviceType)_@Model.ID" @sortProductNr> 654 <label class="form-check-label" for="ProductNumberSort_@(deviceType)_@Model.ID"> 655 @Translate("Product No. (Low)") 656 </label> 657 </div> 658 659 <div class="form-check"> 660 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-ProductNumberSort" id="ProductNumberSortZA_@(deviceType)_@Model.ID" @sortProductNrZA> 661 <label class="form-check-label" for="ProductNumberSortZA_@(deviceType)_@Model.ID"> 662 @Translate("Product No. (High)") 663 </label> 664 </div> 665 } 666 667 @helper RenderCheckboxOption(FacetViewModel facet, FacetOptionViewModel facetOption) 668 { 669 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 670 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 671 string selected = facetOption.Selected ? "checked" : ""; 672 673 if (facetLabel.ToLower() == "true") 674 { 675 facetLabel = Translate("Yes"); 676 } 677 678 if (facetLabel.ToLower() == "false") 679 { 680 facetLabel = Translate("No"); 681 } 682 683 <label class="form-check mt-1" @disabled> 684 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="form-check-input" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected> 685 <span class="form-check-label d-flex align-items-center"> 686 <span class="flex-fill">@Translate(facetLabel) </span> 687 @if (facet.FacetType.ToLower() == "field") { 688 <small class="opacity-85">@facetOption.Count</small> 689 } 690 </span> 691 </label> 692 } 693 694 @helper RenderColorOption(FacetViewModel facet, FacetOptionViewModel facetOption) 695 { 696 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 697 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 698 string selected = facetOption.Selected ? "checked" : ""; 699 700 string image = facetOption.Value; 701 string colorCode = facetOption.Value; 702 703 var variantOption = Dynamicweb.Ecommerce.Services.VariantOptions.GetVariantOption(facetOption.Value.ToString(), Dynamicweb.Ecommerce.Common.Context.LanguageID); 704 if (variantOption != null) 705 { 706 image = variantOption.LargeImage; 707 colorCode = variantOption.Color; 708 } 709 710 <div class="colorbox"> 711 <label> 712 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="@disabled @selected" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected title="@facetOption.Label"> 713 @if (colorCode.Contains("#")) 714 { 715 <span class="colorbox-background" style="background-color: @colorCode"></span> 716 <span class="visually-hidden">@Translate(facetOption.Label)</span> 717 } 718 else 719 { 720 <img class="colorbox-background" src="/Admin/Public/GetImage.ashx?width=25&height=25&image=@image"> 721 <span class="visually-hidden">@Translate(facetOption.Label)</span> 722 } 723 </label> 724 </div> 725 } 726 727