– Common Function Library Project

highlightAndCrop(string, term[, size][, wrap])

Last updated March 24, 2010


Raymond Camden

Version: 2 | Requires: CF6 | Library: StrLib

This UDF will search a string for keywords and return them highlighted. It also crops the string "around" the matched term. Useful on search results pages. This UDF requires ColdFusion 9 only because of the use of var after the beginning of the UDF. It could easily be modified to work in CFMX.

Return Values:
Returns a string.




Name Description Required
string String to scan/crop. Yes
term Search term to find/highlight. Can be a list. Yes
size Size of the cropped string. Defaults to total size of the string. No
wrap The HTML to use to wrap the term. No

Full UDF Source:

 Crops a string and highlights keywords.
 v2 mods by Tuyen (
 @param string 	 String to scan/crop. (Required)
 @param term 	 Search term to find/highlight. Can be a list. (Required)
 @param size 	 Size of the cropped string. Defaults to total size of the string. (Optional)
 @param wrap 	 The HTML to use to wrap the term. (Optional)
 @return Returns a string. 
 @author Raymond Camden ( 
 @version 2, March 24, 2010 
<cffunction name="highlightAndCrop" access="public" output="false" hint="Given an arbitrary string and a search term, find it, and return a 'cropped' set of text around the match.">
	<cfargument name="string" type="string" required="true" hint="Main blob of text">
	<cfargument name="term" type="string" required="true" hint="Keyword to look for.">
	<cfargument name="size" type="numeric" required="false" hint="Size of result string. Defaults to total size of string. Note this is a bit fuzzy - we split it in two and return that amount before and after the match. The size of term and wrap will therefore impact total string length.">
	<cfargument name="wrap" type="string" required="false" default="<b></b>" hint="HTML to wrap the match. MUST be one pair of HTML tags.">

	<cfset var excerpt = "">
	<cfset var pad = "">
	<cfset var match = "">
	<cfset var thisKeyword = "">
	<cfset var end = "">
	<cfset var endInitialTag = "">
	<cfset var beginTag = "">
	<cfset var endTag = "">
	<!--- clean the string --->
	<cfset arguments.string = trim(rereplace(arguments.string, "<.*?>", "", "all"))>

	<!--- pad is half our total --->
	<cfif not structKeyExists(arguments, "size")>
		<cfset arguments.size = len(arguments.string)>
	<cfset pad = ceiling(arguments.size/2)>

	<cfloop list="#arguments.term#" index="thisKeyword">
		<cfif match is 0>
			<cfset match = findNoCase(thisKeyword, arguments.string)>
		<cfelseif findNoCase(thisKeyword, arguments.string) lt match>
			<cfset match = findNoCase(thisKeyword, arguments.string)>
	<cfif match lte pad>
		<cfset match = 1>
	<cfset end = match + len(arguments.term) + arguments.size>

	<!--- now create the main string around the match --->
	<cfif len(arguments.string) gt arguments.size>
		<cfif match gt 1>
			<cfset excerpt = "..." & mid(arguments.string, match-pad, end-match)>
			<cfset excerpt = left(arguments.string,end)>
		<cfif len(arguments.string) gt end>
			<cfset excerpt = excerpt & "...">
		<cfset excerpt = arguments.string>

	<!--- split up my wrap - I bet this can be done better... --->
	<cfset endInitialTag = find(">",arguments.wrap)>
	<cfset beginTag = left(arguments.wrap, endInitialTag)>
	<cfset endTag = mid(arguments.wrap, endInitialTag+1, len(arguments.wrap))>

	<cfloop list="#arguments.term#" index="thisKeyword">
		<cfset excerpt = reReplaceNoCase(excerpt, "(#thisKeyword#)", "#beginTag#\1#endTag#","all")>
	<cfreturn excerpt>
blog comments powered by Disqus


Latest Additions

Kevin Cotton added
May 5, 2016

Raymond Camden added
April 25, 2016

Chris Wigginton added
January 18, 2016

Gary Stanton added
November 19, 2015

Sebastiaan Naafs - van Dijk added
November 13, 2015

Created by Raymond Camden / Design by Justin Johnson