Blog

How building managers and maintenance providers can work together
READ POSTOtis Elevator Blog
An error occurred while processing the template.
The following has evaluated to null or missing: ==> parentCategories [in template "20101#20128#369263930" at line 31, column 89] ---- Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: ${parentCategories?size} [in template "20101#20128#369263930" at line 31, column 87] ----
1<#assign hasCategories = false />
2<#assign currentLocale = themeDisplay.getLanguageId()?lower_case />
3
4<#if entries?has_content>
5 <input type="hidden" name="entries" value="${entries?size}" />
6 <div class="blog-filter filter_listing_event">
7 <div class="blog-filter news_listing_filters">
8 <nav id="topicMenu" class=" blog-filter blog-filter-options">
9 <div class="blog-filter right_label_filter_accordion">
10 <h4>
11 <span style="font-size:14px; font-family: Nunito-sans, sans-serif; color:#ffffff; font-weight:bold;"><@liferay_ui.message key="filter-by-topic" /></span>
12 </h4>
13 </div>
14 <div id="right_filter_accordion">
15 <#list entries as entry>
16 <#assign vocabularyId = entry.getVocabularyId() />
17 <input type="hidden" name="VocabularyId" value="${vocabularyId}" />
18 <#assign categories = entry.getCategories() />
19 <input type="hidden" name="categories" value="${categories?size}" />
20
21 <#if serviceLocator??>
22 <#assign
23 assetCategoryService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryLocalService")
24 />
25 </#if>
26 <#if assetCategoryService??>
27 <#assign
28 parentCategories = assetCategoryService.getVocabularyRootCategories(vocabularyId,-1,-1,null)
29 />
30 </#if>
31 <input type="hidden" name="parentCategories" value="${parentCategories?size}" />
32 <@loadParentCategory parentCategories=parentCategories />
33 </#list>
34
35 <#if !hasCategories>
36 <label class="blog-filter switch form-check-label d-flex align-items-center justify-content-between px-4 py-5">
37 <div class="blog-filter title-text">
38 <span class="blog-filter title"><@liferay_ui.message key="there-are-no-categories" /></span>
39 </div>
40 </label>
41 </#if>
42 </div>
43 </nav>
44 </div>
45 </div>
46</#if>
47
48<#macro loadParentCategory
49 parentCategories
50>
51 <#if parentCategories?has_content>
52 <#list parentCategories as parentCategory>
53 <#if currentLocale == parentCategory.getName()?lower_case >
54 <#if serviceLocator??>
55 <#assign
56 assetCategoryService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryService")
57 childCategories = assetCategoryService.getChildCategories(parentCategory.getCategoryId())
58 />
59 <#if childCategories?has_content>
60 <#assign hasCategories = true />
61 <@displayCategories childCategories=childCategories />
62 </#if>
63 </#if>
64 </#if>
65 </#list>
66 </#if>
67</#macro>
68
69<#macro displayCategories
70 childCategories
71>
72 <#if childCategories?has_content>
73 <#list childCategories as childCategory>
74 <#assign categoryURL = renderResponse.createRenderURL() />
75 ${categoryURL.setParameter("resetCur", "true")}
76 ${categoryURL.setParameter("categoryId", childCategory.getCategoryId()?string)}
77 <label class="blog-filter switch form-check-label d-flex align-items-center justify-content-between px-4" for="${childCategory.getName()}">
78 <div class="blog-filter title-text">
79 <span class="blog-filter title">${childCategory.getName()}</span>
80 </div>
81 <input class="blog-filter form-check-input filter-item" name="category" onChange="handleCategoryFilter(this)" type="checkbox" data-filter="resource" value="${childCategory.getCategoryId()?string}" id="${childCategory.getCategoryId()?string}">
82 </label>
83 <#assign
84 assetCategoryService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetCategoryService")
85 childCategories2 = assetCategoryService.getChildCategories(childCategory.getCategoryId())
86 />
87 <@displayCategories childCategories=childCategories2 />
88 </#list>
89 </#if>
90</#macro>
91
92<script>
93 function handleCategoryFilter(element){
94 console.log("element >>> ",element)
95 // Get all checked checkboxes (adjust selector as needed)
96 const checkedCheckboxes = document.querySelectorAll('input[type="checkbox"][name="category"]:checked');
97
98 checkedCheckboxes.forEach(checkbox=>{
99 if(element.id !== checkbox.id){
100 checkbox.checked = false;
101 }
102 })
103
104 let categoryId = "";
105 if(element.checked){
106 categoryId = element.value;
107 }
108
109 // Get current URL parts
110 const currentUrl = window.location.href;
111 const urlObj = new URL(currentUrl);
112 const pathParts = urlObj.pathname.split('/');
113
114 if(categoryId){
115 // Check if categories segment exists
116 const categoriesIndex = pathParts.findIndex(part => part === 'categories');
117
118 if (categoriesIndex !== -1) {
119 // Replace existing category IDs
120 pathParts[categoriesIndex + 1] = categoryId;
121 } else {
122 // Add new categories segment
123 // Find where to insert (before query parameters)
124 const insertPosition = pathParts[pathParts.length - 1] === ''
125 ? pathParts.length - 1
126 : pathParts.length;
127 pathParts.splice(insertPosition, 0, '-/categories', categoryId);
128 }
129 }else{
130 // Check if categories segment exists
131 const categoriesIndex = pathParts.findIndex(part => part === 'categories');
132 if (categoriesIndex !== -1) {
133 pathParts.splice(categoriesIndex -1);
134 }
135 }
136
137 // Rebuild the URL
138 urlObj.pathname = pathParts.join('/');
139 const newUrl = urlObj.toString();
140
141 console.log("New URL:", newUrl);
142 window.location.href = newUrl; // Uncomment to navigate
143}
144
145
146 document.addEventListener('DOMContentLoaded', function() {
147 // Extract category IDs from URL
148 const url = new URL(window.location.href);
149 const pathParts = url.pathname.split('/');
150 const categoriesIndex = pathParts.findIndex(part => part === 'categories');
151
152 if (categoriesIndex !== -1 && pathParts.length > categoriesIndex + 1) {
153 const categoryIds = pathParts[categoriesIndex + 1].split(',');
154
155 // Check the corresponding checkboxes
156 categoryIds.forEach(id => {
157 const checkbox = document.querySelector('input[type="checkbox"][value="'+id+'"]');
158 if (checkbox) {
159 checkbox.checked = true;
160 } else {
161 console.warn('Checkbox with value "'+id+'" not found');
162 }
163 });
164
165 console.log('Checked '+categoryIds.length+' category checkboxes');
166 } else {
167 console.log('No category IDs found in URL');
168 }
169});
170
171</script>
172
173<style>
174.blog-filter .blog-filter-options {
175 background-color: #eceae8
176}
177
178.blog-filter .right_label_filter_accordion {
179 background-color: #041e42;
180 padding-left: 20px
181}
182
183.event-listing-custom .blog-filter .card .blog-filter.article_space .blog-listing__post-button-wrapper {
184 bottom: 0;
185 margin: 15px 0 20px;
186 position: absolute
187}
188
189.event-listing-custom .blog-filter .card .blog-filter.article_space {
190 border: 1px solid rgba(0,0,0,.125);
191 border-radius: .25rem;
192 height: 100%;
193 position: relative
194}
195
196.event-listing-custom .blog-filter .card .blog-filter.article_space .blog-listing__post-content {
197 padding: 30px 20px
198}
199
200.event-listing-custom .blog-listing__post-tags a.blog-listing__post-tag {
201 width: auto!important
202}
203
204section.blog-filter .container-wrap {
205 margin: 0 auto;
206 max-width: 1300px
207}
208
209.event-listing-custom .blog-filter .card .blog-filter.article_space .featured_image_content {
210 line-height: 0
211}
212
213.event-listing-custom .blog-filter .card .blog-filter.article_space .blog-listing__post-content h2.blog-listing__post-title {
214 margin: 0
215}
216
217section.blog-filter #products article.blog-filter h2.blog-listing__post-title a {
218 margin-bottom: 18px;
219 text-transform: capitalize
220}
221
222.event-listing-custom .blog-filter .card .blog-filter.article_space a.blog-listing__post-tag {
223 color: #f65275;
224 font-weight: 700;
225 margin-bottom: 15px!important;
226 text-transform: capitalize
227}
228
229.event-listing-custom .blog-filter .card .blog-filter.article_space .blog-listing__post-content .blog-listing__post-summary p {
230 color: #041e42;
231 line-height: 22px;
232 margin-bottom: 30px
233}
234
235.event-listing-custom .blog-filter .card .blog-filter.article_space:hover {
236 box-shadow: 0 1px 4px rgba(0,0,0,.16);
237 transition: all .4s ease-in-out
238}
239
240.right_sort_filter_left label span.blog-filter.right_sort_filter_left_span {
241 padding-right: 20px
242}
243
244#right_filter_accordion .switch.form-check-label {
245 border-bottom: 1px solid rgb(217, 217, 217);
246 padding: 15px;
247}
248
249@media only screen and (max-width: 767px) {
250
251 .blog-filter-options.active .right_label_filter_accordion:after {
252 top: 42%;
253 transform: rotate(180deg)
254 }
255
256 .Two_column .event-listing-custom .blog-listing .card {
257 width: 100%!important
258 }
259
260 .article_space .blog-listing__post-button.button {
261 padding: 10px 22px
262 }
263}
264
265h2.entry-title.taglib-categorization-filter {
266 display: none;
267}
268
269</style>
Node: liferay-86cf696f85-tb99t:8080: