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