PageRenderTime 12ms CodeModel.GetById 2ms app.highlight 5ms RepoModel.GetById 2ms app.codeStats 0ms

/wheels/view/links.cfm

http://cfwheels.googlecode.com/
ColdFusion | 328 lines | 305 code | 11 blank | 12 comment | 46 complexity | b07c141e415919084bfbf7f313c10f7c MD5 | raw file
  1<cffunction name="linkTo" returntype="string" access="public" output="false" hint="Creates a link to another page in your application. Pass in the name of a `route` to use your configured routes or a `controller`/`action`/`key` combination. Note: Pass any additional arguments like `class`, `rel`, and `id`, and the generated tag will also include those values as HTML attributes."
  2	examples=
  3	'
  4		##linkTo(text="Log Out", controller="account", action="logout")##
  5		-> <a href="/account/logout">Log Out</a>
  6
  7		<!--- if you''re already in the `account` controller, Wheels will assume that''s where you want the link to point --->
  8		##linkTo(text="Log Out", action="logout")##
  9		-> <a href="/account/logout">Log Out</a>
 10
 11		##linkTo(text="View Post", controller="blog", action="post", key=99)##
 12		-> <a href="/blog/post/99">View Post</a>
 13
 14		##linkTo(text="View Settings", action="settings", params="show=all&sort=asc")##
 15		-> <a href="/account/settings?show=all&amp;sort=asc">View Settings</a>
 16
 17		<!--- Given that a `userProfile` route has been configured in `config/routes.cfm` --->
 18		##linkTo(text="Joe''s Profile", route="userProfile", userName="joe")##
 19		-> <a href="/user/joe">Joe''s Profile</a>
 20		
 21		<!--- Link to an external website --->
 22		##linkTo(text="ColdFusion Framework", href="http://cfwheels.org/")##
 23		-> <a href="http://cfwheels.org/">ColdFusion Framework</a>
 24		
 25		<!--- Remote link --->
 26		##linkTo(text="View Settings", action="settings", params="show=all&sort=asc", remote="true")##
 27		-> <a data-remote="true" href="/account/settings?show=all&amp;sort=asc">View Settings</a>
 28		
 29		<!--- Give the link `class` and `id` attributes --->
 30		##linkTo(text="Delete Post", action="delete", key=99, class="delete", id="delete-99")##
 31		-> <a class="delete" href="/blog/delete/99" id="delete-99">Delete Post</a>
 32	'
 33	categories="view-helper,links" chapters="linking-pages" functions="URLFor,buttonTo,mailTo">
 34	<cfargument name="text" type="string" required="false" default="" hint="The text content of the link.">
 35	<cfargument name="confirm" type="string" required="false" default="" hint="Pass a message here to cause a JavaScript confirmation dialog box to pop up containing the message.">
 36	<cfargument name="route" type="string" required="false" default="" hint="See documentation for @URLFor.">
 37	<cfargument name="controller" type="string" required="false" default="" hint="See documentation for @URLFor.">
 38	<cfargument name="action" type="string" required="false" default="" hint="See documentation for @URLFor.">
 39	<cfargument name="key" type="any" required="false" default="" hint="See documentation for @URLFor.">
 40	<cfargument name="params" type="string" required="false" default="" hint="See documentation for @URLFor.">
 41	<cfargument name="anchor" type="string" required="false" default="" hint="See documentation for @URLFor.">
 42	<cfargument name="onlyPath" type="boolean" required="false" hint="See documentation for @URLFor.">
 43	<cfargument name="host" type="string" required="false" hint="See documentation for @URLFor.">
 44	<cfargument name="protocol" type="string" required="false" hint="See documentation for @URLFor.">
 45	<cfargument name="port" type="numeric" required="false" hint="See documentation for @URLFor.">
 46	<cfargument name="href" type="string" required="false" hint="Pass a link to an external site here if you want to bypass the Wheels routing system altogether and link to an external URL.">
 47	<cfargument name="remote" type="boolean" required="false" hint="Pass true if you wish to make this an asynchronous request">
 48	<cfscript>
 49		var loc = {};
 50		loc.returnValue = $args(name="linkTo", cachable=true, args=arguments);
 51		if (!StructKeyExists(loc, "returnValue"))
 52		{
 53			// only run our linkTo code if we do not have a cached result
 54			if (Len(arguments.confirm))
 55				arguments["data-confirm"] = JSStringFormat(arguments.confirm);
 56			if (StructKeyExists(arguments, "remote") && IsBoolean(arguments.remote))
 57				arguments["data-remote"] = arguments.remote;
 58			if (!StructKeyExists(arguments, "href"))
 59				arguments.href = URLFor(argumentCollection=arguments);
 60			arguments.href = toXHTML(arguments.href);
 61			if (!Len(arguments.text))
 62				arguments.text = arguments.href;
 63			loc.skip = "text,confirm,route,controller,action,key,params,anchor,onlyPath,host,protocol,port,remote";
 64			if (Len(arguments.route))
 65				loc.skip = ListAppend(loc.skip, $routeVariables(argumentCollection=arguments)); // variables passed in as route arguments should not be added to the html element
 66			loc.returnValue = $element(name="a", skip=loc.skip, content=arguments.text, attributes=arguments);
 67		}
 68	</cfscript>
 69	<cfreturn loc.returnValue>
 70</cffunction>
 71
 72<cffunction name="buttonTo" returntype="string" access="public" output="false" hint="Creates a form containing a single button that submits to the URL. The URL is built the same way as the @linkTo function."
 73	examples=
 74	'
 75		##buttonTo(text="Delete Account", action="perFormDelete", disable="Wait...")##
 76	'
 77	categories="view-helper,links" functions="URLFor,linkTo,mailTo">
 78	<cfargument name="text" type="string" required="false" hint="The text content of the button.">
 79	<cfargument name="confirm" type="string" required="false" hint="See documentation for @linkTo.">
 80	<cfargument name="image" type="string" required="false" hint="If you want to use an image for the button pass in the link to it here (relative from the `images` folder).">
 81	<cfargument name="disable" type="any" required="false" hint="Pass in `true` if you want the button to be disabled when clicked (can help prevent multiple clicks), or pass in a string if you want the button disabled and the text on the button updated (to ""please wait..."", for example).">
 82	<cfargument name="route" type="string" required="false" default="" hint="See documentation for @URLFor.">
 83	<cfargument name="controller" type="string" required="false" default="" hint="See documentation for @URLFor.">
 84	<cfargument name="action" type="string" required="false" default="" hint="See documentation for @URLFor.">
 85	<cfargument name="key" type="any" required="false" default="" hint="See documentation for @URLFor.">
 86	<cfargument name="params" type="string" required="false" default="" hint="See documentation for @URLFor.">
 87	<cfargument name="anchor" type="string" required="false" default="" hint="See documentation for @URLFor.">
 88	<cfargument name="onlyPath" type="boolean" required="false" hint="See documentation for @URLFor.">
 89	<cfargument name="host" type="string" required="false" hint="See documentation for @URLFor.">
 90	<cfargument name="protocol" type="string" required="false" hint="See documentation for @URLFor.">
 91	<cfargument name="port" type="numeric" required="false" hint="See documentation for @URLFor.">
 92	<cfargument name="remote" type="boolean" required="false" hint="See documentation for @linkTo.">
 93	<cfscript>
 94		var loc = {};
 95		$args(name="buttonTo", reserved="method", args=arguments);
 96		arguments.action = URLFor(argumentCollection=arguments);
 97		arguments.action = toXHTML(arguments.action);
 98		arguments.method = "post";
 99		if (Len(arguments.confirm))
100			loc.submitTagArguments["data-confirm"] = JSStringFormat(arguments.confirm);
101		if (StructKeyExists(arguments, "remote") && IsBoolean(arguments.remote))
102			arguments["data-remote"] = arguments.remote;
103		if (Len(arguments.disable))
104			loc.submitTagArguments["data-disable-with"] = JSStringFormat(arguments.disable);
105		
106		loc.submitTagArguments.value = arguments.text;
107		loc.submitTagArguments.image = arguments.image;
108		loc.content = submitTag(argumentCollection=loc.submitTagArguments);
109		loc.skip = "disable,image,text,confirm,route,controller,key,params,anchor,onlyPath,host,protocol,port,remote";
110		if (Len(arguments.route))
111			loc.skip = ListAppend(loc.skip, $routeVariables(argumentCollection=arguments)); // variables passed in as route arguments should not be added to the html element
112		loc.returnValue = $element(name="form", skip=loc.skip, content=loc.content, attributes=arguments);
113	</cfscript>
114	<cfreturn loc.returnValue>
115</cffunction>
116
117<cffunction name="mailTo" returntype="string" access="public" output="false" hint="Creates a `mailto` link tag to the specified email address, which is also used as the name of the link unless name is specified."
118	examples=
119	'
120		##mailTo(emailAddress="webmaster@yourdomain.com", name="Contact our Webmaster")##
121		-> <a href="mailto:webmaster@yourdomain.com">Contact our Webmaster</a>
122	'
123	categories="view-helper,links" functions="URLFor,linkTo,buttonTo">
124	<cfargument name="emailAddress" type="string" required="true" hint="The email address to link to.">
125	<cfargument name="name" type="string" required="false" default="" hint='A string to use as the link text ("Joe" or "Support Department", for example).'>
126	<cfargument name="encode" type="boolean" required="false" hint="Pass `true` here to encode the email address, making it harder for bots to harvest it for example.">
127	<cfscript>
128		var loc = {};
129		$args(name="mailTo", reserved="href", args=arguments);
130		arguments.href = "mailto:#arguments.emailAddress#";
131		if (Len(arguments.name))
132			loc.content = arguments.name;
133		else
134			loc.content = arguments.emailAddress;
135		loc.returnValue = $element(name="a", skip="emailAddress,name,encode", content=loc.content, attributes=arguments);
136		if (arguments.encode)
137		{
138			loc.js = "document.write('#Trim(loc.returnValue)#');";
139			loc.encoded = "";
140			loc.iEnd = Len(loc.js);
141			for (loc.i=1; loc.i LTE loc.iEnd; loc.i=loc.i+1)
142			{
143				loc.encoded = loc.encoded & "%" & Right("0" & FormatBaseN(Asc(Mid(loc.js,loc.i,1)),16),2);
144			}
145			loc.content = "eval(unescape('#loc.encoded#'))";
146			loc.returnValue = $element(name="script", content=loc.content, type="text/javascript");
147		}
148	</cfscript>
149	<cfreturn loc.returnValue>
150</cffunction>
151
152<cffunction name="paginationLinks" returntype="string" access="public" output="false" hint="Builds and returns a string containing links to pages based on a paginated query. Uses @linkTo internally to build the link, so you need to pass in a `route` name or a `controller`/`action`/`key` combination. All other @linkTo arguments can be supplied as well, in which case they are passed through directly to @linkTo. If you have paginated more than one query in the controller, you can use the `handle` argument to reference them. (Don't forget to pass in a `handle` to the @findAll function in your controller first.)"
153	examples=
154	'
155		<!--- Example 1: List authors page by page, 25 at a time --->
156		<!--- Controller code --->
157		<cfparam name="params.page" default="1">
158		<cfset allAuthors = model("author").findAll(page=params.page, perPage=25, order="lastName")>
159
160		<!--- View code --->
161		<ul>
162		    <cfoutput query="allAuthors">
163		        <li>##firstName## ##lastName##</li>
164		    </cfoutput>
165		</ul>
166		<cfoutput>##paginationLinks(action="listAuthors")##</cfoutput>
167		
168		<!--- Example 2: Using the same model call above, show all authors with a window size of 5 --->
169		<!--- View code --->
170		<cfoutput>##paginationLinks(action="listAuthors", windowSize=5)##</cfoutput>
171
172		<!--- Example 3: If more than one paginated query is being run, then you need to reference the correct `handle` in the view --->
173		<!--- Controller code --->
174		<cfset allAuthors = model("author").findAll(handle="authQuery", page=5, order="id")>
175
176		<!--- View code --->
177		<ul>
178		    <cfoutput>##paginationLinks(action="listAuthors", handle="authQuery", prependToLink="<li>", appendToLink="</li>")##</cfoutput>
179		</ul>
180
181		<!--- Example 4: Call to `paginationLinks` using routes --->
182		<!--- Route setup in config/routes.cfm --->
183		<cfset addRoute(name="paginatedCommentListing", pattern="blog/[year]/[month]/[day]/[page]", controller="theBlog", action="stats")>
184		<cfset addRoute(name="commentListing", pattern="blog/[year]/[month]/[day]",  controller="theBlog", action="stats")>
185
186		<!--- Ccontroller code --->
187		<cfparam name="params.page" default="1">
188		<cfset comments = model("comment").findAll(page=params.page, order="createdAt")>
189
190		<!--- View code --->
191		<ul>
192		    <cfoutput>##paginationLinks(route="paginatedCommentListing", year=2009, month="feb", day=10)##</cfoutput>
193		</ul>
194	'
195	categories="view-helper,links" chapters="getting-paginated-data,displaying-links-for-pagination" functions="pagination,setPagination,linkTo,findAll">
196	<cfargument name="windowSize" type="numeric" required="false" hint="The number of page links to show around the current page.">
197	<cfargument name="alwaysShowAnchors" type="boolean" required="false" hint="Whether or not links to the first and last page should always be displayed.">
198	<cfargument name="anchorDivider" type="string" required="false" hint="String to place next to the anchors on either side of the list.">
199	<cfargument name="linkToCurrentPage" type="boolean" required="false" hint="Whether or not the current page should be linked to.">
200	<cfargument name="prepend" type="string" required="false" hint="String or HTML to be prepended before result.">
201	<cfargument name="append" type="string" required="false" hint="String or HTML to be appended after result.">
202	<cfargument name="prependToPage" type="string" required="false" hint="String or HTML to be prepended before each page number.">
203	<cfargument name="prependOnFirst" type="boolean" required="false" hint="Whether or not to prepend the `prependToPage` string on the first page in the list.">
204	<cfargument name="prependOnAnchor" type="boolean" required="false" hint="Whether or not to prepend the `prependToPage` string on the anchors.">
205	<cfargument name="appendToPage" type="string" required="false" hint="String or HTML to be appended after each page number.">
206	<cfargument name="appendOnLast" type="boolean" required="false" hint="Whether or not to append the `appendToPage` string on the last page in the list.">
207	<cfargument name="appendOnAnchor" type="boolean" required="false" hint="Whether or not to append the `appendToPage` string on the anchors.">
208	<cfargument name="classForCurrent" type="string" required="false" hint="Class name for the current page number (if `linkToCurrentPage` is `true`, the class name will go on the `a` element. If not, a `span` element will be used).">
209	<cfargument name="handle" type="string" required="false" default="query" hint="The handle given to the query that the pagination links should be displayed for.">
210	<cfargument name="name" type="string" required="false" hint="The name of the param that holds the current page number.">
211	<cfargument name="showSinglePage" type="boolean" required="false" hint="Will show a single page when set to `true`. (The default behavior is to return an empty string when there is only one page in the pagination).">
212	<cfargument name="pageNumberAsParam" type="boolean" required="false" hint="Decides whether to link the page number as a param or as part of a route. (The default behavior is `true`).">
213
214	<cfscript>
215		var loc = {};
216		$args(name="paginationLinks", args=arguments);
217		loc.skipArgs = "windowSize,alwaysShowAnchors,anchorDivider,linkToCurrentPage,prepend,append,prependToPage,prependOnFirst,prependOnAnchor,appendToPage,appendOnLast,appendOnAnchor,classForCurrent,handle,name,showSinglePage,pageNumberAsParam";
218		loc.linkToArguments = Duplicate(arguments);
219		loc.iEnd = ListLen(loc.skipArgs);
220		for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
221			StructDelete(loc.linkToArguments, ListGetAt(loc.skipArgs, loc.i));
222		loc.currentPage = pagination(arguments.handle).currentPage;
223		loc.totalPages = pagination(arguments.handle).totalPages;
224		loc.start = "";
225		loc.middle = "";
226		loc.end = "";
227		if (arguments.showSinglePage || loc.totalPages > 1)
228		{
229			if (Len(arguments.prepend))
230				loc.start = loc.start & arguments.prepend;
231			if (arguments.alwaysShowAnchors)
232			{
233				if ((loc.currentPage - arguments.windowSize) > 1)
234				{
235					loc.pageNumber = 1;
236					if (!arguments.pageNumberAsParam)
237					{
238						loc.linkToArguments[arguments.name] = loc.pageNumber;
239					}
240					else
241					{
242						loc.linkToArguments.params = arguments.name & "=" & loc.pageNumber;
243						if (StructKeyExists(arguments, "params"))
244							loc.linkToArguments.params = loc.linkToArguments.params & "&" & arguments.params;
245					}
246					loc.linkToArguments.text = loc.pageNumber;
247					if (Len(arguments.prependToPage) && arguments.prependOnAnchor)
248						loc.start = loc.start & arguments.prependToPage;
249					loc.start = loc.start & linkTo(argumentCollection=loc.linkToArguments);
250					if (Len(arguments.appendToPage) && arguments.appendOnAnchor)
251						loc.start = loc.start & arguments.appendToPage;
252					loc.start = loc.start & arguments.anchorDivider;
253				}
254			}
255			loc.middle = "";
256			for (loc.i=1; loc.i <= loc.totalPages; loc.i++)
257			{
258				if ((loc.i >= (loc.currentPage - arguments.windowSize) && loc.i <= loc.currentPage) || (loc.i <= (loc.currentPage + arguments.windowSize) && loc.i >= loc.currentPage))
259				{
260					if (!arguments.pageNumberAsParam)
261					{
262						loc.linkToArguments[arguments.name] = loc.i;
263					}
264					else
265					{
266						loc.linkToArguments.params = arguments.name & "=" & loc.i;
267						if (StructKeyExists(arguments, "params"))
268							loc.linkToArguments.params = loc.linkToArguments.params & "&" & arguments.params;
269					}
270					loc.linkToArguments.text = loc.i;
271					if (Len(arguments.classForCurrent) && loc.currentPage == loc.i)
272						loc.linkToArguments.class = arguments.classForCurrent;
273					else
274						StructDelete(loc.linkToArguments, "class");
275					if (Len(arguments.prependToPage))
276						loc.middle = loc.middle & arguments.prependToPage;
277					if (loc.currentPage != loc.i || arguments.linkToCurrentPage)
278					{
279						loc.middle = loc.middle & linkTo(argumentCollection=loc.linkToArguments);
280					}
281					else
282					{
283						if (Len(arguments.classForCurrent))
284							loc.middle = loc.middle & $element(name="span", content=loc.i, class=arguments.classForCurrent);
285						else
286							loc.middle = loc.middle & loc.i;
287					}
288					if (Len(arguments.appendToPage))
289						loc.middle = loc.middle & arguments.appendToPage;
290				}
291			}
292			if (arguments.alwaysShowAnchors)
293			{
294				if (loc.totalPages > (loc.currentPage + arguments.windowSize))
295				{
296					if (!arguments.pageNumberAsParam)
297					{
298						loc.linkToArguments[arguments.name] = loc.totalPages;
299					}
300					else
301					{
302						loc.linkToArguments.params = arguments.name & "=" & loc.totalPages;
303						if (StructKeyExists(arguments, "params"))
304							loc.linkToArguments.params = loc.linkToArguments.params & "&" & arguments.params;
305					}
306					loc.linkToArguments.text = loc.totalPages;
307					loc.end = loc.end & arguments.anchorDivider;
308					if (Len(arguments.prependToPage) && arguments.prependOnAnchor)
309						loc.end = loc.end & arguments.prependToPage;
310					loc.end = loc.end & linkTo(argumentCollection=loc.linkToArguments);
311					if (Len(arguments.appendToPage) && arguments.appendOnAnchor)
312						loc.end = loc.end & arguments.appendToPage;
313				}
314			}
315			if (Len(arguments.append))
316				loc.end = loc.end & arguments.append;
317		}
318		if (Len(loc.middle))
319		{
320			if (Len(arguments.prependToPage) && !arguments.prependOnFirst)
321				loc.middle = Mid(loc.middle, Len(arguments.prependToPage)+1, Len(loc.middle)-Len(arguments.prependToPage));
322			if (Len(arguments.appendToPage) && !arguments.appendOnLast)
323				loc.middle = Mid(loc.middle, 1, Len(loc.middle)-Len(arguments.appendToPage));
324		}
325		loc.returnValue = loc.start & loc.middle & loc.end;
326	</cfscript>
327	<cfreturn loc.returnValue>
328</cffunction>