PageRenderTime 194ms CodeModel.GetById 110ms app.highlight 3ms RepoModel.GetById 77ms app.codeStats 1ms

/wheels/view/text.cfm

http://cfwheels.googlecode.com/
ColdFusion | 317 lines | 306 code | 9 blank | 2 comment | 15 complexity | 3f4789c146dd35ffe12cb99a9d6eda78 MD5 | raw file
  1<cffunction name="autoLink" returntype="string" access="public" output="false" hint="Turns all URLs and email addresses into hyperlinks."
  2	examples=
  3	'
  4		##autoLink("Download Wheels from http://cfwheels.org/download")##
  5		-> Download Wheels from <a href="http://cfwheels.org/download">http://cfwheels.org/download</a>
  6
  7		##autoLink("Email us at info@cfwheels.org")##
  8		-> Email us at <a href="mailto:info@cfwheels.org">info@cfwheels.org</a>
  9	'
 10	categories="view-helper,text" functions="excerpt,highlight,simpleFormat,titleize,truncate">
 11	<cfargument name="text" type="string" required="true" hint="The text to create links in.">
 12	<cfargument name="link" type="string" required="false" hint="Whether to link URLs, email addresses or both. Possible values are: `all` (default), `URLs` and `emailAddresses`.">
 13	<cfscript>
 14		var loc = {};
 15		$args(name="autoLink", args=arguments);
 16		if (arguments.link != "emailAddresses")
 17		{
 18			arguments.regex = "(?:(?:<a\s[^>]+)?(?:https?://|www\.|\/)[^\s\b]+)";
 19			arguments.text = $autoLinkLoop(argumentCollection=arguments);
 20		}
 21		if (arguments.link != "URLs")
 22		{
 23			arguments.regex = "(?:(?:<a\s[^>]+)?(?:[^@\s]+)@(?:(?:[-a-z0-9]+\.)+[a-z]{2,}))";
 24			arguments.protocol = "mailto:";
 25			arguments.text = $autoLinkLoop(argumentCollection=arguments);
 26		}
 27	</cfscript>
 28	<cfreturn arguments.text>
 29</cffunction>
 30
 31<cffunction name="$autoLinkLoop" access="public" returntype="string" output="false">
 32	<cfargument name="text" type="string" required="true">
 33	<cfargument name="regex" type="string" required="true">
 34	<cfargument name="protocol" type="string" required="false" default="">
 35	<cfscript>
 36	var loc = {};
 37	loc.PunctuationRegEx = "([^\w\/-]+)$";
 38	loc.startPosition = 1;
 39	loc.match = ReFindNoCase(arguments.regex, arguments.text, loc.startPosition, true);
 40	while(loc.match.pos[1] gt 0)
 41	{
 42		loc.startPosition = loc.match.pos[1] + loc.match.len[1];
 43		loc.str = Mid(arguments.text, loc.match.pos[1], loc.match.len[1]);
 44		if (Left(loc.str, 2) neq "<a")
 45		{
 46			arguments.text = RemoveChars(arguments.text, loc.match.pos[1], loc.match.len[1]);
 47			// remove any sort of trailing puncuation
 48			loc.punctuation = ArrayToList(ReMatchNoCase(loc.PunctuationRegEx, loc.str));
 49			loc.str = REReplaceNoCase(loc.str, loc.PunctuationRegEx, "", "all");
 50			arguments.href = arguments.protocol & loc.str;
 51			loc.element = $element("a", arguments, loc.str, "text,regex,link,domains,protocol") & loc.punctuation;
 52			arguments.text = Insert(loc.element, arguments.text, loc.match.pos[1]-1);
 53			loc.startPosition = loc.match.pos[1] + len(loc.element);
 54		}
 55		loc.startPosition++;
 56		loc.match = ReFindNoCase(arguments.regex, arguments.text, loc.startPosition, true);
 57	}
 58	</cfscript>
 59	<cfreturn arguments.text>
 60</cffunction>
 61
 62<cffunction name="excerpt" returntype="string" access="public" output="false" hint="Extracts an excerpt from text that matches the first instance of a given phrase."
 63	examples=
 64	'
 65		##excerpt(text="ColdFusion Wheels is a Rails-like MVC framework for Adobe ColdFusion and Railo", phrase="framework", radius=5)##
 66		-> ... MVC framework for ...
 67	'
 68	categories="view-helper,text" functions="autoLink,highlight,simpleFormat,titleize,truncate">
 69	<cfargument name="text" type="string" required="true" hint="The text to extract an excerpt from.">
 70	<cfargument name="phrase" type="string" required="true" hint="The phrase to extract.">
 71	<cfargument name="radius" type="numeric" required="false" hint="Number of characters to extract surrounding the phrase.">
 72	<cfargument name="excerptString" type="string" required="false" hint="String to replace first and/or last characters with.">
 73	<cfargument name="stripTags" type="boolean" required="false" hint="Should we remove all html tags before extracting the except">
 74	<cfargument name="wholeWords" type="boolean" required="false" hint="when extracting the exceprt, span to to grab whole words.">
 75	<cfscript>
 76	var loc = {};
 77	$args(name="excerpt", args=arguments);
 78	// by default we return a blank string
 79	loc.returnValue = "";
 80	// strip all html tags from text
 81	if (arguments.stripTags)
 82	{
 83		// have to append "this" since we have a method
 84		// with the same name
 85		arguments.text = this.stripTags(arguments.text);
 86	}
 87	// see if phrase exists in text
 88	loc.pos = FindNoCase(arguments.phrase, arguments.text, 1);
 89	// no need to go further if phrase isn't found
 90	if (loc.pos eq 0)
 91	{
 92		return loc.returnValue;
 93	}
 94
 95	loc.textLen = Len(arguments.text);
 96	loc.phraseLen = Len(arguments.phrase);
 97	loc.startPos = loc.pos - arguments.radius;
 98	loc.truncateStart = arguments.excerptString;
 99
100	if (loc.startPos <= 1)
101	{
102		loc.startPos = 1;
103		loc.truncateStart = "";
104	}
105
106	loc.endPos = loc.pos + loc.phraseLen + arguments.radius;
107	loc.truncateEnd = arguments.excerptString;
108
109	if (loc.endPos > loc.textLen)
110	{
111		// need to compensate for the fact that
112		// loc.startPos is at least 1
113		loc.endPos = loc.textLen + 1;
114		loc.truncateEnd = "";
115	}
116
117	if (arguments.wholeWords)
118	{
119		if (loc.startPos > 1)
120		{
121			loc._startPos = len(arguments.text) - loc.startPos;
122			loc.pad = loc._startPos - refind("[[:space:]]", reverse(arguments.text), loc._startPos);
123			loc.startPos = loc.startPos - loc.pad;
124
125			// when endPos gte textLen, need to subtract one to get
126			// the correct startPos
127			if (loc.endPos >= loc.textLen)
128			{
129				loc.startPos = loc.startPos - 1;
130			}
131		}
132
133		if (loc.endPos < loc.textLen)
134		{
135			loc.endPos = refind("[[:space:]]", arguments.text, loc.endPos);
136		}
137	}
138
139	loc.returnValue = loc.truncateStart & Mid(arguments.text, loc.startPos, (loc.endPos - loc.startPos)) & loc.truncateEnd;
140	</cfscript>
141	<cfreturn loc.returnValue>
142</cffunction>
143
144<cffunction name="highlight" returntype="string" access="public" output="false" hint="Highlights the phrase(s) everywhere in the text if found by wrapping it in a `span` tag."
145	examples=
146	'
147		##highlight(text="You searched for: Wheels", phrases="Wheels")##
148		-> You searched for: <span class="highlight">Wheels</span>
149	'
150	categories="view-helper,text" functions="autoLink,excerpt,simpleFormat,titleize,truncate">
151	<cfargument name="text" type="string" required="true" hint="Text to search.">
152	<cfargument name="phrases" type="string" required="true" hint="List of phrases to highlight.">
153	<cfargument name="class" type="string" required="false" hint="Class to use in `span` tags surrounding highlighted phrase(s).">
154	<cfscript>
155		var loc = {};
156		$args(name="highlight", args=arguments);
157		if (!Len(arguments.text) || !Len(arguments.phrases))
158		{
159			loc.returnValue = arguments.text;
160		}
161		else
162		{
163			loc.origText = arguments.text;
164			loc.iEnd = ListLen(arguments.phrases);
165			for (loc.i=1; loc.i <= loc.iEnd; loc.i=loc.i+1)
166			{
167				loc.newText = "";
168				loc.phrase = Trim(ListGetAt(arguments.phrases, loc.i));
169				loc.pos = 1;
170				while (FindNoCase(loc.phrase, loc.origText, loc.pos))
171				{
172					loc.foundAt = FindNoCase(loc.phrase, loc.origText, loc.pos);
173					loc.prevText = Mid(loc.origText, loc.pos, loc.foundAt-loc.pos);
174					loc.newText = loc.newText & loc.prevText;
175					if (Find("<", loc.origText, loc.foundAt) < Find(">", loc.origText, loc.foundAt) || !Find(">", loc.origText, loc.foundAt))
176						loc.newText = loc.newText & "<span class=""" & arguments.class & """>" & Mid(loc.origText, loc.foundAt, Len(loc.phrase)) & "</span>";
177					else
178						loc.newText = loc.newText & Mid(loc.origText, loc.foundAt, Len(loc.phrase));
179					loc.pos = loc.foundAt + Len(loc.phrase);
180				}
181				loc.newText = loc.newText & Mid(loc.origText, loc.pos, Len(loc.origText) - loc.pos + 1);
182				loc.origText = loc.newText;
183			}
184			loc.returnValue = loc.newText;
185		}
186	</cfscript>
187	<cfreturn loc.returnValue>
188</cffunction>
189
190<cffunction name="simpleFormat" returntype="string" access="public" output="false" hint="Replaces single newline characters with HTML break tags and double newline characters with HTML paragraph tags (properly closed to comply with XHTML standards)."
191	examples=
192	'
193		<!--- How most of your calls will look --->
194		##simpleFormat(post.comments)##
195
196		<!--- Demonstrates what output looks like with specific data --->
197		<cfsavecontent variable="comment">
198			I love this post!
199
200			Here''s why:
201			* Short
202			* Succinct
203			* Awesome
204		</cfsavecontent>
205		##simpleFormat(comment)##
206		-> <p>I love this post!</p>
207		   <p>
208		       Here''s why:<br />
209			   * Short<br />
210			   * Succinct<br />
211			   * Awesome
212		   </p>
213	'
214	categories="view-helper,text" functions="autoLink,excerpt,highlight,titleize,truncate">
215	<cfargument name="text" type="string" required="true" hint="The text to format.">
216	<cfargument name="wrap" type="boolean" required="false" hint="Set to `true` to wrap the result in a paragraph.">
217	<cfargument name="escapeHtml" type="boolean" required="false" hint="Whether or not to escape HTML characters before applying the line break formatting.">
218	<cfscript>
219		$args(name="simpleFormat", args=arguments);
220
221		// If we're escaping HTML along with applying the line break formatting
222		if(arguments.escapeHtml)
223		{
224			arguments.text = $htmlFormat(arguments.text);
225		}
226
227		arguments.text = Trim(arguments.text);
228
229		arguments.text = Replace(arguments.text, "#Chr(13)#", "", "all");
230		arguments.text = Replace(arguments.text, "#Chr(10)##Chr(10)#", "</p><p>", "all");
231		arguments.text = Replace(arguments.text, "#Chr(10)#", "<br />", "all");
232
233		// add back in our returns so we can strip the tags and re-apply them without issue
234		// this is good to be edited the textarea text in it's original format (line returns)
235		arguments.text = Replace(arguments.text, "</p><p>", "</p>#Chr(10)##Chr(10)#<p>", "all");
236		arguments.text = Replace(arguments.text, "<br />", "<br />#Chr(10)#", "all");
237
238		if (arguments.wrap)
239			arguments.text = "<p>" & arguments.text & "</p>";
240	</cfscript>
241	<cfreturn arguments.text>
242</cffunction>
243
244<cffunction name="titleize" returntype="string" access="public" output="false" hint="Capitalizes all words in the text to create a nicer looking title."
245	examples=
246	'
247		##titleize("Wheels is a framework for ColdFusion")##
248		-> Wheels Is A Framework For ColdFusion
249	'
250	categories="view-helper,text" functions="autoLink,excerpt,highlight,simpleFormat,truncate">
251	<cfargument name="word" type="string" required="true" hint="The text to turn into a title.">
252	<cfscript>
253		var loc = {};
254		loc.returnValue = "";
255		loc.iEnd = ListLen(arguments.word, " ");
256		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
257		{
258			loc.returnValue = ListAppend(loc.returnValue, capitalize(ListGetAt(arguments.word, loc.i, " ")), " ");
259		}
260	</cfscript>
261	<cfreturn loc.returnValue>
262</cffunction>
263
264<cffunction name="truncate" returntype="string" access="public" output="false" hint="Truncates text to the specified length and replaces the last characters with the specified truncate string (which defaults to ""..."")."
265	examples=
266	'
267		##truncate(text="Wheels is a framework for ColdFusion", length=20)##
268		-> Wheels is a frame...
269
270		##truncate(text="Wheels is a framework for ColdFusion", truncateString=" (more)")##
271		-> Wheels is a framework f (more)
272	'
273	categories="view-helper,text" functions="autoLink,excerpt,highlight,simpleFormat,titleize">
274	<cfargument name="text" type="string" required="true" hint="The text to truncate.">
275	<cfargument name="length" type="numeric" required="false" hint="Length to truncate the text to.">
276	<cfargument name="truncateString" type="string" required="false" hint="String to replace the last characters with.">
277	<cfscript>
278		$args(name="truncate", args=arguments);
279		if (Len(arguments.text) gt arguments.length)
280		{
281			arguments.text = Left(arguments.text, arguments.length-Len(arguments.truncateString)) & arguments.truncateString;
282		}
283	</cfscript>
284	<cfreturn arguments.text>
285</cffunction>
286
287<cffunction name="wordTruncate" returntype="string" access="public" output="false" hint="Truncates text to the specified length of words and replaces the remaining characters with the specified truncate string (which defaults to ""..."")."
288	examples=
289	'
290		##wordTruncate(text="Wheels is a framework for ColdFusion", length=4)##
291		-> Wheels is a framework...
292
293		##truncate(text="Wheels is a framework for ColdFusion", truncateString=" (more)")##
294		-> Wheels is a framework for (more)
295	'
296	categories="view-helper,text" functions="autoLink,excerpt,highlight,simpleFormat,titleize">
297	<cfargument name="text" type="string" required="true" hint="The text to truncate.">
298	<cfargument name="length" type="numeric" required="false" hint="Number of words to truncate the text to.">
299	<cfargument name="truncateString" type="string" required="false" hint="String to replace the last characters with.">
300	<cfscript>
301		var loc = {};
302		$args(name="wordTruncate", args=arguments);
303		loc.wordArray = ListToArray(arguments.text, " ", false);
304		loc.wordLen = ArrayLen(loc.wordArray);
305
306		if (loc.wordLen gt arguments.length)
307		{
308			arguments.text = "";
309			for (loc.i = 1; loc.i lte arguments.length; loc.i++)
310			{
311				arguments.text = ListAppend(arguments.text, loc.wordArray[loc.i], " ");
312			}
313			arguments.text = arguments.text & arguments.truncateString;
314		}
315	</cfscript>
316	<cfreturn arguments.text>
317</cffunction>