Skip to content

Commit

Permalink
Fix Filter Options Highlighting (#1871)
Browse files Browse the repository at this point in the history
Previously, when we moved from innerHTML to textContent, it broke the filter options highlighting since the <strong> tag is no longer applied properly. This PR fixes the issue while still avoid insecure document method.
  • Loading branch information
EmilyZhang777 authored Mar 12, 2024
1 parent bd429a2 commit 11e9f35
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 4 deletions.
50 changes: 50 additions & 0 deletions src/core/models/highlightedvalue.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ export default class HighlightedValue {
return this.buildHighlightedValue(this.value, this.matchedSubstrings);
}

/**
* get highlighted value elements
* @returns {Array<Element|string>}
*/
getElements () {
this._sortMatchedSubstrings();
return this._buildHighlightedElements(this.value, this.matchedSubstrings);
}

/**
* get highlighted value string
* @param {Function} transformFunction takes a string and returns the transformed string
Expand Down Expand Up @@ -135,6 +144,47 @@ export default class HighlightedValue {
return highlightedValue;
}

/**
* introduces highlighting to input data according to highlighting specifiers and returns a
* list of elements/strings
*
* @param {Object} val input object to apply highlighting to
* @param {Object} highlightedSubstrings highlighting specifiers to apply to input object
* @returns {Array<Element|string>} a list of elements/strings representing the val with
* highlighting applied. Example returned value :
* [
* 'Save time & bank on your terms at over 1,800',
* <strong>ATM</strong>,
* ]
*/
_buildHighlightedElements (val, highlightedSubstrings) {
const highlightedElements = [];
let nextStart = 0;

for (let j = 0; j < highlightedSubstrings.length; j++) {
const start = Number(highlightedSubstrings[j].offset);
const end = start + highlightedSubstrings[j].length;

if (nextStart < start) {
highlightedElements.push(val.slice(nextStart, start));
}

if (start < end) {
const highlightedText = document.createElement('strong');
highlightedText.textContent = val.slice(start, end);
highlightedElements.push(highlightedText);
}

if (j === highlightedSubstrings.length - 1 && end < val.length) {
highlightedElements.push(val.slice(end));
}

nextStart = end;
}

return highlightedElements;
}

_sortMatchedSubstrings () {
this.matchedSubstrings.sort((a, b) => {
if (a.offset < b.offset) {
Expand Down
7 changes: 5 additions & 2 deletions src/ui/components/filters/filteroptionscomponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -455,10 +455,13 @@ export default class FilterOptionsComponent extends Component {
if (matchedSubstring) {
filterOption.classList.add('displaySearch');
filterOption.classList.remove('hiddenSearch');
labelEl.textContent = new HighlightedValue({
const highlightedElements = new HighlightedValue({
value: labelText,
matchedSubstrings: [matchedSubstring]
}).get();
}).getElements();

labelEl.textContent = '';
highlightedElements.forEach(el => labelEl.append(el));
} else {
filterOption.classList.add('hiddenSearch');
filterOption.classList.remove('displaySearch');
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/components/filters/filteroptionscomponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,10 @@ describe('filter options component', () => {
const filterOptionEl = filterOptionEls.at(index);
expect(filterOptionEl.hasClass(index === 0 ? 'displaySearch' : 'hiddenSearch')).toBeTruthy();
expect(filterOptionEl.hasClass(index === 0 ? 'hiddenSearch' : 'displaySearch')).toBeFalsy();
expect(filterOptionEl.find('.js-yxt-FilterOptions-optionLabel--name').text().trim())
.toEqual(index === 0 ? '<strong>cir</strong>i' : options[index].label);
const labelNameEl = filterOptionEl.find('.js-yxt-FilterOptions-optionLabel--name');
if (index === 0) {
expect(labelNameEl.find('strong').text()).toEqual('cir');
}
}
});

Expand Down

0 comments on commit 11e9f35

Please sign in to comment.