module SimpleSearch module ViewHelper # Example: # # <%= order_by :name %> # <%= order_by :name, 'Company Name' %> # <%= order_by :name, 'Company Name', :class=>'bold' %> def order_link(attr, name=nil, html_options={}) raise Exception, "must be used in a view" unless (request.fullpath && request.parameters) # check if order_by is in an url array matches = request.fullpath.match Regexp.new("[\&\?]([a-z_]+)\\[order_by\\]=") # &array[order_by] order_arr_key = (matches && matches.length == 2) ? matches[1] : nil # get order_by value order_by_value = order_arr_key ? request.parameters[order_arr_key][:order_by] : request.parameters[:order_by] if order_by_value order_by_col, current_order = order_by_value.split(" ") else order_by_col, current_order = attr, nil end # determine next order next_order = {nil=>'asc', 'asc'=>'desc', 'desc'=>'asc'}[current_order] # build new url params new_url_params = if order_arr_key old_arr = request.parameters[order_arr_key] new_arr = old_arr.merge(:order_by => "#{order_by_col} #{next_order}") request.parameters.merge(order_arr_key => new_arr) else request.parameters.merge(:order_by => "#{order_by_col} #{next_order}" ) end # build link text name ||= attr.to_s.humanize.titleize.strip order_indicator = {nil=>'', 'asc'=>'▲', 'desc'=>'▼'}[current_order] link_text = "#{name} #{order_indicator}".strip link_to link_text, new_url_params, html_options end # # Returns page related properties in hash # def page_properties(arel) total_rows = arel.limit(1000000).offset(0).count # check if page is in an url array matches = request.fullpath.match Regexp.new("\&([a-z_]+)\\[page|page_by\\]=") # &array[page] page_arr_key = (matches && matches.length == 2) ? matches[1] : nil # get current page value page = page_arr_key ? request.parameters[page_arr_key][:page] : request.parameters[:page] page ||= 1 page = page.to_i page_by = page_arr_key ? request.parameters[page_arr_key][:page_by] : request.parameters[:page_by] page_by ||= 30 page_by = page_by.to_i last_page = total_rows / page_by.to_i last_page += 1 if total_rows % page_by.to_i != 0 { :total_rows => total_rows, :last_page => last_page, :current_page => (page || 1).to_i, :rows_per_page => (page_by || 30).to_i, :page_arr_key => page_arr_key } end # # Returns a url params in hash for the page number given # def page_params(page_num, page_arr_key=nil) params = if page_arr_key old_arr = request.parameters[page_arr_key].with_indifferent_access request.parameters.merge(page_arr_key => old_arr.merge(:page => page_num) ) else request.parameters.merge(:page => page_num ) end params.with_indifferent_access end # # Returns page url params in hash with the page number as key # def page_url_params(arel, num_pages=5) page_props = page_properties(arel) num_bf_af = (num_pages-1)/2 current_page = page_props[:current_page] last_page = page_props[:last_page] page_numbers = [1, last_page] page_numbers << ([current_page-num_bf_af,1].max..[current_page+num_bf_af,last_page].min).to_a page_numbers << last_page page_numbers = page_numbers.flatten.uniq.sort page_url_params = {} for num in page_numbers page_url_params[num] = page_params(num, page_props[:page_arr_key]) end page_url_params end def page_urls(arel, http_options={}) page_urls = [] prev_page = 0 page_url_params(arel).each { |page, url_params| if page.to_i > (prev_page+1) # page number jumped up, need to have some indicator page_urls << "..." end page_urls << link_to(page, url_params, http_options) prev_page = page } page_urls end end end