|
59 | 59 | instantsearch.widgets.stats({ |
60 | 60 | container: '#stats', |
61 | 61 | templates: { |
62 | | - text: `<h1> |
| 62 | + text: `<h1> |
63 | 63 | Search results ({{#helpers.formatNumber}}{{nbHits}}{{/helpers.formatNumber}}) |
64 | 64 | </h1>`, |
65 | 65 | }, |
|
78 | 78 | const groupNameKey = breadcrumbsKeys.shift(); |
79 | 79 | const entryNameKey = breadcrumbsKeys.pop(); |
80 | 80 | const newItem = { |
| 81 | + groupNameKey, |
81 | 82 | entryNameKey, |
82 | 83 | breadcrumbsKeys, |
83 | 84 | item: getClearedItem(item), |
84 | 85 | }; |
85 | 86 | const groupChildren = outputItemsMap[groupNameKey]?.children ?? []; |
86 | 87 |
|
87 | 88 | outputItemsMap[groupNameKey] = { |
88 | | - groupNameKey, |
89 | 89 | children: [...groupChildren, newItem], |
90 | 90 | }; |
91 | 91 | }); |
|
94 | 94 | }, |
95 | 95 | templates: { |
96 | 96 | item: (hit) => { |
97 | | - const { groupNameKey, children } = hit; |
98 | | - const groupItem = children[0].item; |
99 | | - const groupHeaderHTML = `<h2 class="instantsearch__group-header"> |
100 | | - ${instantsearch.highlight({ attribute: `hierarchy.${groupNameKey}`, highlightedTagName: 'mark', hit: groupItem })} |
101 | | - (${children.length}) |
102 | | - </h2>`; |
| 97 | + const {children} = hit; |
| 98 | + let resultHTML = ''; |
| 99 | + let previousGroupName = null; |
| 100 | + let groupChildCount = 0; |
103 | 101 | let groupContentHTML = ''; |
104 | 102 |
|
105 | | - children.forEach((childHit) => { |
106 | | - const { breadcrumbsKeys, entryNameKey, item: entryItem } = childHit; |
| 103 | + children.forEach((childHit, index) => { |
| 104 | + const {groupNameKey, breadcrumbsKeys, entryNameKey, item: entryItem} = childHit; |
107 | 105 | const headerHTML = `<h3 class="instantsearch__entry-header"> |
108 | | - ${instantsearch.highlight({ attribute: `hierarchy.${entryNameKey}`, highlightedTagName: 'mark', hit: entryItem })} |
| 106 | + ${instantsearch.highlight({ |
| 107 | + attribute: `hierarchy.${entryNameKey}`, |
| 108 | + highlightedTagName: 'mark', |
| 109 | + hit: entryItem |
| 110 | + })} |
109 | 111 | </h3>`; |
110 | 112 | let breadcrumbsHTML = ''; |
111 | 113 | let contentHTML = ''; |
112 | 114 |
|
113 | 115 | if (entryItem.content) { |
114 | 116 | contentHTML = `<div class="instantsearch__entry-content"> |
115 | | - ${instantsearch.highlight({ attribute: `content`, highlightedTagName: 'mark', hit: entryItem })} |
| 117 | + ${instantsearch.highlight({ |
| 118 | + attribute: `content`, |
| 119 | + highlightedTagName: 'mark', |
| 120 | + hit: entryItem |
| 121 | + })} |
116 | 122 | </div>`; |
117 | 123 | } |
118 | 124 |
|
119 | 125 | breadcrumbsKeys?.forEach((breadcrumbKey) => { |
120 | 126 | breadcrumbsHTML += `<span class="instantsearch__entry-breadcrumbs-item"> |
121 | | - ${instantsearch.highlight({ attribute: `hierarchy.${breadcrumbKey}`, highlightedTagName: 'mark', hit: entryItem })} |
| 127 | + ${instantsearch.highlight({ |
| 128 | + attribute: `hierarchy.${breadcrumbKey}`, |
| 129 | + highlightedTagName: 'mark', |
| 130 | + hit: entryItem |
| 131 | + })} |
122 | 132 | </span>` |
123 | 133 | }); |
124 | 134 |
|
|
130 | 140 | </div> |
131 | 141 | </a>`; |
132 | 142 |
|
133 | | - groupContentHTML += childHTML; |
| 143 | + let groupName = childHit.item.hierarchy[groupNameKey]; |
| 144 | + if (index && groupName != previousGroupName) { |
| 145 | + // Not first and in a new group |
| 146 | + if (children.length === index + 1) { |
| 147 | + // Not first, last and in a new group: close previous group, close current group |
| 148 | + let groupHeaderHTML = `<h2 class="instantsearch__group-header"> |
| 149 | + ${previousGroupName} |
| 150 | + (${groupChildCount}) |
| 151 | + </h2>`; |
| 152 | + resultHTML += `${groupHeaderHTML} |
| 153 | + <div class="instantsearch__group"> |
| 154 | + ${groupContentHTML} |
| 155 | + </div>`; |
| 156 | + groupHeaderHTML = `<h2 class="instantsearch__group-header"> |
| 157 | + ${groupName} |
| 158 | + (1) |
| 159 | + </h2>`; |
| 160 | + resultHTML += `${groupHeaderHTML} |
| 161 | + <div class="instantsearch__group"> |
| 162 | + ${childHTML} |
| 163 | + </div>`; |
| 164 | + } else { |
| 165 | + // Not first, not last and in new group: close previous group, add to next group content |
| 166 | + let groupHeaderHTML = `<h2 class="instantsearch__group-header"> |
| 167 | + ${previousGroupName} |
| 168 | + (${groupChildCount}) |
| 169 | + </h2>`; |
| 170 | + resultHTML += `${groupHeaderHTML} |
| 171 | + <div class="instantsearch__group"> |
| 172 | + ${groupContentHTML} |
| 173 | + </div>`; |
| 174 | + groupContentHTML = childHTML; |
| 175 | + groupChildCount = 1; |
| 176 | + } |
| 177 | + } else if (children.length === index + 1) { |
| 178 | + // Last and in previous group: add to previous group and close previous group |
| 179 | + groupContentHTML += childHTML; |
| 180 | + groupChildCount++; |
| 181 | + let groupHeaderHTML = `<h2 class="instantsearch__group-header"> |
| 182 | + ${groupName} |
| 183 | + (${groupChildCount}) |
| 184 | + </h2>`; |
| 185 | + resultHTML += `${groupHeaderHTML} |
| 186 | + <div class="instantsearch__group"> |
| 187 | + ${groupContentHTML} |
| 188 | + </div>`; |
| 189 | + } else { |
| 190 | + // Not last and in previous group: add to previous group |
| 191 | + groupContentHTML += childHTML; |
| 192 | + groupChildCount++; |
| 193 | + } |
| 194 | + previousGroupName = groupName; |
134 | 195 | }); |
135 | 196 |
|
136 | 197 | return `<div class="instantsearch"> |
137 | | - ${groupHeaderHTML} |
138 | | - <div class="instantsearch__group"> |
139 | | - ${groupContentHTML} |
140 | | - </div> |
| 198 | + ${resultHTML} |
141 | 199 | </div>`; |
142 | 200 | }, |
143 | 201 | }, |
|
0 commit comments