MarkText highlights search terms within specified containers using mark.js by Julien Royer. These examples widen a search term with wildcards, synonyms and diacritics.
The wildcards attribute: ? matches one character, * any number of characters.
The synonyms map highlights synonymous terms in both directions: searching for "one" also highlights "1",
and vice versa.
With diacritics="true" characters with and without diacritics match each other, e.g. "e" matches "é".
<style>
.marktext-highlight,
mark {
background-color: yellow !important;
color: black !important;
}
</style>
<div class="card">
<h5>Wildcard Search</h5>
<p>The <code>wildcards</code> attribute: <code>?</code> matches one character, <code>*</code> any number of characters.</p>
<h:form id="formWildcard">
<p:messages id="messages" showSummary="true" showDetail="true"/>
<h:panelGrid columns="2" columnClasses="label,value" cellpadding="4">
<h:outputText value="Search term:"/>
<p:inputText id="searchInput" value="#{markTextWildcardController.searchTerm}" placeholder="Enter search term">
<p:ajax event="keyup" delay="300" update="markText" process="@this"/>
</p:inputText>
<h:outputText value="Wildcard Mode:"/>
<p:selectOneMenu id="wildcards" value="#{markTextWildcardController.wildcards}">
<f:selectItem itemValue="disabled" itemLabel="Disabled"/>
<f:selectItem itemValue="enabled" itemLabel="Enabled (no spaces)"/>
<f:selectItem itemValue="withSpaces" itemLabel="Enabled (with spaces)"/>
<p:ajax event="change" update="markText" process="@this"/>
</p:selectOneMenu>
</h:panelGrid>
<p:panel id="searchContainer" header="Searchable Content" style="margin-top: 20px">
<p>#{markTextWildcardController.processedText}</p>
</p:panel>
<p:panel id="backendDataPanel" header="Backend Data from Mark Event Listener" style="margin-top: 20px">
<h:outputText value="Last Matched Terms: #{empty markTextWildcardController.lastMatchedTerms ? 'No data received yet' : markTextWildcardController.lastMatchedTerms}"/>
<br/>
<h:outputText value="Last Positions: #{empty markTextWildcardController.lastPositions ? 'No data received yet' : markTextWildcardController.lastPositions}"/>
</p:panel>
<pe:markText id="markText" for="searchContainer" value="#{markTextWildcardController.searchTerm}"
wildcards="#{markTextWildcardController.wildcards}" styleClass="marktext-highlight" caseSensitive="false">
<p:ajax event="mark" listener="#{markTextWildcardController.onHighlight}" update="backendDataPanel messages"/>
</pe:markText>
</h:form>
</div>
<div class="card">
<h5>Synonyms</h5>
<p>
The <code>synonyms</code> map highlights synonymous terms in both directions: searching for "one" also highlights "1",
and vice versa.
</p>
<h:form id="formSynonyms">
<p:messages id="messages" showSummary="true" showDetail="true"/>
<h:panelGrid columns="3" cellpadding="4">
<h:outputText value="Search term:"/>
<p:inputText id="searchInput" value="#{synonymsMarkTextController.searchTerm}" placeholder="Enter search term">
<p:ajax event="keyup" delay="500" update="searchContainer markText"/>
</p:inputText>
<p:commandButton value="Highlight" update="searchContainer markText" icon="pi pi-search"/>
</h:panelGrid>
<p:panel id="searchContainer" header="Searchable Content" style="margin-top: 20px">
<h:panelGroup id="searchContent" layout="block">
#{synonymsMarkTextController.processedText}
</h:panelGroup>
</p:panel>
<pe:markText id="markText" for="searchContent" value="#{synonymsMarkTextController.searchTerm}" synonyms="#{synonymsMarkTextController.synonyms}" styleClass="marktext-highlight">
<p:ajax event="mark" listener="#{synonymsMarkTextController.onHighlight}" update="messages"/>
</pe:markText>
</h:form>
</div>
<div class="card">
<h5>Diacritics</h5>
<p>With <code>diacritics="true"</code> characters with and without diacritics match each other, e.g. "e" matches "é".</p>
<h:form id="formDiacritics">
<p:messages id="messages" showSummary="true" showDetail="true"/>
<h:panelGrid columns="3" cellpadding="4">
<h:outputText value="Search term:"/>
<p:inputText id="searchInput" value="#{diacriticsMarkTextController.searchTerm}" placeholder="Enter search term">
<p:ajax event="keyup" delay="500" update="searchContainer markText"/>
</p:inputText>
<p:commandButton value="Highlight" update="searchContainer markText" icon="pi pi-search"/>
</h:panelGrid>
<h:panelGrid columns="2" style="margin-top:10px" cellpadding="4">
<h:outputText value="Consider diacritics:"/>
<p:selectBooleanCheckbox value="#{diacriticsMarkTextController.diacritics}">
<p:ajax update="markText searchContainer" process="@this"/>
</p:selectBooleanCheckbox>
</h:panelGrid>
<p:panel id="searchContainer" header="Searchable Content" style="margin-top: 20px">
<h:panelGroup id="searchContent" layout="block">
<p>#{diacriticsMarkTextController.processedText}</p>
</h:panelGroup>
</p:panel>
<pe:markText id="markText" widgetVar="markTextWidget" for="searchContent" value="#{diacriticsMarkTextController.searchTerm}"
diacritics="#{diacriticsMarkTextController.diacritics}" styleClass="marktext-highlight">
<p:ajax event="mark" listener="#{diacriticsMarkTextController.onHighlight}" update="messages"/>
</pe:markText>
</h:form>
</div>
package org.primefaces.extensions.showcase.controller.marktext;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.primefaces.extensions.event.MarkEvent;
import org.primefaces.extensions.model.marktext.MarkPosition;
@Named
@ViewScoped
public class MarkTextWildcardController implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String searchTerm = "r*n";
private String wildcards = "enabled"; // disabled | enabled | withSpaces
private String processedText = "The quick brown fox jumps over the lazy dog. "
+ "Running is essential for fitness. "
+ "Programming and design go hand in hand.";
private List<String> lastMatchedTerms = new ArrayList<>();
private List<MarkPosition> lastPositions = new ArrayList<>();
public String getSearchTerm() {
return searchTerm;
}
public void setSearchTerm(String searchTerm) {
this.searchTerm = searchTerm;
}
public String getWildcards() {
return wildcards;
}
public void setWildcards(String wildcards) {
this.wildcards = wildcards;
}
public String getProcessedText() {
return processedText;
}
public List<String> getLastMatchedTerms() {
return lastMatchedTerms;
}
public List<MarkPosition> getLastPositions() {
return lastPositions;
}
public void onHighlight(MarkEvent event) {
this.lastMatchedTerms = event.getMatchedTerms();
this.lastPositions = event.getPositions();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Mark Event Triggered",
"Found " + lastMatchedTerms.size() + " matched terms and " + lastPositions.size() + " positions."));
}
}
package org.primefaces.extensions.showcase.controller.marktext;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.primefaces.extensions.event.MarkEvent;
import org.primefaces.extensions.model.marktext.MarkPosition;
/**
* Synonyms MarkText Controller.
*
* @author jxmai
*/
@Named
@ViewScoped
public class SynonymsMarkTextController implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String searchTerm = "one";
private Map<String, String> synonyms = new HashMap<String, String>() {
{
put("one", "1");
put("two", "2");
put("three", "3");
put("four", "4");
put("five", "5");
}
};
private String processedText = "Counting is easy: one, two, three, four, five. "
+ "Numbers: 1, 2, 3, 4, 5. "
+ "You can use either words or digits: one (1), two (2), three (3). "
+ "This demonstrates synonyms highlighting both ways.";
private List<String> lastMatchedTerms = new ArrayList<>();
private List<MarkPosition> lastPositions = new ArrayList<>();
private String lastMatchedTermsJson;
private String lastPositionsJson;
public String getSearchTerm() {
return searchTerm;
}
public void setSearchTerm(String searchTerm) {
this.searchTerm = searchTerm;
}
public Map<String, String> getSynonyms() {
return synonyms;
}
public void setSynonyms(Map<String, String> synonyms) {
this.synonyms = synonyms;
}
public String getProcessedText() {
return processedText;
}
public void setProcessedText(String processedText) {
this.processedText = processedText;
}
public List<String> getLastMatchedTerms() {
return lastMatchedTerms;
}
public List<MarkPosition> getLastPositions() {
return lastPositions;
}
public void onHighlight(MarkEvent event) {
this.lastMatchedTerms = event.getMatchedTerms();
this.lastPositions = event.getPositions();
this.lastMatchedTermsJson = lastMatchedTerms.toString();
this.lastPositionsJson = lastPositions.stream()
.map(MarkPosition::toString)
.collect(Collectors.joining(", "));
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Mark Event Triggered",
"Found " + lastMatchedTerms.size() + " matched terms and " + lastPositions.size() + " positions."));
}
public String getLastMatchedTermsJson() {
return lastMatchedTermsJson;
}
public void setLastMatchedTermsJson(String lastMatchedTermsJson) {
this.lastMatchedTermsJson = lastMatchedTermsJson;
}
public String getLastPositionsJson() {
return lastPositionsJson;
}
public void setLastPositionsJson(String lastPositionsJson) {
this.lastPositionsJson = lastPositionsJson;
}
}
package org.primefaces.extensions.showcase.controller.marktext;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.primefaces.extensions.event.MarkEvent;
import org.primefaces.extensions.model.marktext.MarkPosition;
/**
* Diacritics behavior example for MarkText.
*
* @author jxmai
*/
@Named
@ViewScoped
public class DiacriticsMarkTextController implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String searchTerm = "cafe";
private Boolean diacritics = Boolean.TRUE;
private String processedText = "Café, caFe, cafe, façade, naive, naïve, résumé, resume.";
private List<String> lastMatchedTerms = new ArrayList<>();
private List<MarkPosition> lastPositions = new ArrayList<>();
public String getSearchTerm() {
return searchTerm;
}
public void setSearchTerm(String searchTerm) {
this.searchTerm = searchTerm;
}
public Boolean getDiacritics() {
return diacritics;
}
public void setDiacritics(Boolean diacritics) {
this.diacritics = diacritics;
}
public String getProcessedText() {
return processedText;
}
public void setProcessedText(String processedText) {
this.processedText = processedText;
}
public List<String> getLastMatchedTerms() {
return lastMatchedTerms;
}
public List<MarkPosition> getLastPositions() {
return lastPositions;
}
public void onHighlight(MarkEvent event) {
this.lastMatchedTerms = event.getMatchedTerms();
this.lastPositions = event.getPositions();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Mark Event Triggered",
"Found " + lastMatchedTerms.size() + " matched terms and " + lastPositions.size() + " positions."));
}
}