You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sort_helper.rb 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. # Helpers to sort tables using clickable column headers.
  2. #
  3. # Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
  4. # License: This source code is released under the MIT license.
  5. #
  6. # - Consecutive clicks toggle the column's sort order.
  7. # - Sort state is maintained by a session hash entry.
  8. # - Icon image identifies sort column and state.
  9. # - Typically used in conjunction with the Pagination module.
  10. #
  11. # Example code snippets:
  12. #
  13. # Controller:
  14. #
  15. # helper :sort
  16. # include SortHelper
  17. #
  18. # def list
  19. # sort_init 'last_name'
  20. # sort_update
  21. # @items = Contact.find_all nil, sort_clause
  22. # end
  23. #
  24. # Controller (using Pagination module):
  25. #
  26. # helper :sort
  27. # include SortHelper
  28. #
  29. # def list
  30. # sort_init 'last_name'
  31. # sort_update
  32. # @contact_pages, @items = paginate :contacts,
  33. # :order_by => sort_clause,
  34. # :per_page => 10
  35. # end
  36. #
  37. # View (table header in list.rhtml):
  38. #
  39. # <thead>
  40. # <tr>
  41. # <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
  42. # <%= sort_header_tag('last_name', :caption => 'Name') %>
  43. # <%= sort_header_tag('phone') %>
  44. # <%= sort_header_tag('address', :width => 200) %>
  45. # </tr>
  46. # </thead>
  47. #
  48. # - The ascending and descending sort icon images are sort_asc.png and
  49. # sort_desc.png and reside in the application's images directory.
  50. # - Introduces instance variables: @sort_name, @sort_default.
  51. # - Introduces params :sort_key and :sort_order.
  52. #
  53. module SortHelper
  54. # Initializes the default sort column (default_key) and sort order
  55. # (default_order).
  56. #
  57. # - default_key is a column attribute name.
  58. # - default_order is 'asc' or 'desc'.
  59. # - name is the name of the session hash entry that stores the sort state,
  60. # defaults to '<controller_name>_sort'.
  61. #
  62. def sort_init(default_key, default_order='asc', name=nil)
  63. @sort_name = name || @params[:controller] + @params[:action] + '_sort'
  64. @sort_default = {:key => default_key, :order => default_order}
  65. end
  66. # Updates the sort state. Call this in the controller prior to calling
  67. # sort_clause.
  68. #
  69. def sort_update()
  70. if @params[:sort_key]
  71. sort = {:key => @params[:sort_key], :order => @params[:sort_order]}
  72. elsif @session[@sort_name]
  73. sort = @session[@sort_name] # Previous sort.
  74. else
  75. sort = @sort_default
  76. end
  77. @session[@sort_name] = sort
  78. end
  79. # Returns an SQL sort clause corresponding to the current sort state.
  80. # Use this to sort the controller's table items collection.
  81. #
  82. def sort_clause()
  83. @session[@sort_name][:key] + ' ' + @session[@sort_name][:order]
  84. end
  85. # Returns a link which sorts by the named column.
  86. #
  87. # - column is the name of an attribute in the sorted record collection.
  88. # - The optional caption explicitly specifies the displayed link text.
  89. # - A sort icon image is positioned to the right of the sort link.
  90. #
  91. def sort_link(column, caption=nil)
  92. key, order = @session[@sort_name][:key], @session[@sort_name][:order]
  93. if key == column
  94. if order.downcase == 'asc'
  95. icon = 'sort_asc'
  96. order = 'desc'
  97. else
  98. icon = 'sort_desc'
  99. order = 'asc'
  100. end
  101. else
  102. icon = nil
  103. order = 'desc' # changed for desc order by default
  104. end
  105. caption = titleize(Inflector::humanize(column)) unless caption
  106. params = {:params => {:sort_key => column, :sort_order => order}}
  107. link_to_remote(caption,
  108. {:update => "content", :url => { :sort_key => column, :sort_order => order}},
  109. {:href => url_for(:params => { :sort_key => column, :sort_order => order})}) +
  110. (icon ? nbsp(2) + image_tag(icon) : '')
  111. end
  112. # Returns a table header <th> tag with a sort link for the named column
  113. # attribute.
  114. #
  115. # Options:
  116. # :caption The displayed link name (defaults to titleized column name).
  117. # :title The tag's 'title' attribute (defaults to 'Sort by :caption').
  118. #
  119. # Other options hash entries generate additional table header tag attributes.
  120. #
  121. # Example:
  122. #
  123. # <%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>
  124. #
  125. # Renders:
  126. #
  127. # <th title="Sort by contact ID" width="40">
  128. # <a href="/contact/list?sort_order=desc&amp;sort_key=id">Id</a>
  129. # &nbsp;&nbsp;<img alt="Sort_asc" src="/images/sort_asc.png" />
  130. # </th>
  131. #
  132. def sort_header_tag(column, options = {})
  133. if options[:caption]
  134. caption = options[:caption]
  135. options.delete(:caption)
  136. else
  137. caption = titleize(Inflector::humanize(column))
  138. end
  139. options[:title]= "Sort by #{caption}" unless options[:title]
  140. content_tag('th', sort_link(column, caption), options)
  141. end
  142. private
  143. # Return n non-breaking spaces.
  144. def nbsp(n)
  145. '&nbsp;' * n
  146. end
  147. # Return capitalized title.
  148. def titleize(title)
  149. title.split.map {|w| w.capitalize }.join(' ')
  150. end
  151. end