module ActiveList class SimpleRenderer < ActiveList::Renderer DATATYPE_ABBREVIATION = { :binary => :bin, :boolean => :bln, :date => :dat, :datetime => :dtt, :decimal => :dec, :float =>:flt, :integer =>:int, :string =>:str, :text => :txt, :time => :tim, :timestamp => :dtt } def remote_update_code(table) code = "if params[:column] and params[:visibility]\n" code << " column = params[:column].to_s\n" code << " list_params[:hidden_columns].delete(column) if params[:visibility] == 'shown'\n" code << " list_params[:hidden_columns] << column if params[:visibility] == 'hidden'\n" code << " head :ok\n" code << "elsif params[:only]\n" code << " render(:inline=>'<%=#{table.view_method_name}(:only => params[:only])-%>')\n" code << "else\n" code << " render(:inline=>'<%=#{table.view_method_name}-%>')\n" code << "end\n" return code end def build_table_code(table) record = "r" child = "c" colgroup = columns_definition_code(table) header = header_code(table) extras = extras_code(table) tbody = columns_to_cells(table, :body, :record=>record) code = table.select_data_code code << "tbody = ' (#{table.records_variable_name}_offset + 1), :y => (#{table.records_variable_name}_offset+#{table.records_variable_name}_limit), :total => #{table.records_variable_name}_count)+'\"" end code << ">'\n" code << "if #{table.records_variable_name}_count > 0\n" code << " reset_cycle('list')\n" code << " for #{record} in #{table.records_variable_name}\n" line_class = "cycle('odd', 'even', :name=>'list')+' r'+#{record}.id.to_s" line_class << "+' '+("+table.options[:line_class].to_s.gsub(/RECORD/, record)+').to_s' unless table.options[:line_class].nil? code << " tbody << content_tag(:tr, (#{tbody}).html_safe, :class=>#{line_class})\n" if table.options[:children].is_a? Symbol children = table.options[:children].to_s child_tbody = columns_to_cells(table, :children, :record=>child) code << " for #{child} in #{record}.#{children}\n" code << " tbody << content_tag(:tr, (#{child_tbody}).html_safe, {:class=>#{line_class}+' child'})\n" code << " end\n" end code << " end\n" code << "else\n" code << " tbody << '' + ::I18n.translate('list.no_records') + ''\n" code << "end\n" code << "tbody << ''\n" code << "return tbody.html_safe if options[:only] == 'body' or options[:only] == 'tbody'\n" code << "html = ''\n" code << "html << '
'#{table.controller_method_name}'}))+'\" class=\"active-list\"" code << " data-list-current-page=\"' + #{table.records_variable_name}_page.to_s + '\" data-list-page-size=\"' + #{table.records_variable_name}_limit.to_s + '\"" code << " data-list-sort-by=\"' + list_params[:sort].to_s + '\" data-list-sort-dir=\"' + list_params[:dir].to_s + '\"" code << ">'\n" code << "html << ''\n" code << "html << (#{header})\n" code << "if block_given?\n" code << " html << ''+capture("+table.columns.collect{|c| {:name=>c.name, :id=>c.id}}.inspect+", &block)+''\n" code << "end\n" code << "html << tbody\n" code << "html << '
'\n" code << "html << #{extras}\n" if extras code << "html << '
'\n" code << "return html.html_safe\n" return code end def columns_to_cells(table, nature, options={}) columns = table.columns code = '' record = options[:record]||'RECORD' for column in columns if nature==:header raise Exception.new("Ohohoh") else case column.class.name when DataColumn.name style = column.options[:style]||'' style = style.gsub(/RECORD/, record)+"+" if style.match(/RECORD/) style << "'" if nature!=:children or (not column.options[:children].is_a? FalseClass and nature==:children) datum = column.datum_code(record, nature==:children) if column.datatype == :boolean datum = "content_tag(:div, '', :class=>'checkbox-'+("+datum.to_s+" ? 'true' : 'false'))" end if [:date, :datetime, :timestamp].include? column.datatype datum = "(#{datum}.nil? ? '' : ::I18n.localize(#{datum}))" end if !column.options[:currency].is_a?(FalseClass) and (currency = column.options[:currency]) # column.datatype == :decimal and currency = currency[nature] if currency.is_a?(Hash) currency = :currency if currency.is_a?(TrueClass) currency = "RECORD.#{currency}" if currency.is_a?(Symbol) raise Exception.new("Option :currency is not valid. Hash, Symbol or true/false") unless currency.is_a?(String) currency.gsub!(/RECORD/, record) datum = "(#{datum}.nil? ? '' : ::I18n.localize(#{datum}, :currency => #{currency}))" elsif column.datatype == :decimal datum = "(#{datum}.nil? ? '' : ::I18n.localize(#{datum}))" end if column.options[:url].is_a?(TrueClass) and nature==:body datum = "(#{datum}.blank? ? '' : link_to(#{datum}, {:controller=>:#{column.class_name.underscore.pluralize}, :action=>:show, :id=>#{column.record_expr(record)+'.id'}}))" elsif column.options[:url].is_a?(Hash) and nature==:body column.options[:url][:id] ||= column.record_expr(record)+'.id' column.options[:url][:action] ||= :show column.options[:url][:controller] ||= column.class_name.underscore.pluralize.to_sym url = column.options[:url].collect{|k, v| ":#{k}=>"+(v.is_a?(String) ? v.gsub(/RECORD/, record) : v.inspect)}.join(", ") datum = "(#{datum}.blank? ? '' : link_to(#{datum}, url_for(#{url})))" elsif column.options[:mode] == :download# and !datum.nil? datum = "(#{datum}.blank? ? '' : link_to(tg('download'), url_for_file_column("+record+",'#{column.name}')))" elsif column.options[:mode]||column.name == :email # datum = 'link_to('+datum+', "mailto:#{'+datum+'}")' datum = "(#{datum}.blank? ? '' : mail_to(#{datum}))" elsif column.options[:mode]||column.name == :website datum = "(#{datum}.blank? ? '' : link_to("+datum+", "+datum+"))" elsif column.name==:color style << "background: #'+"+column.datum_code(record)+"+';" elsif column.name.to_s.match(/(^|\_)currency$/) and column.datatype == :string and column.limit == 3 datum = "(#{datum}.blank? ? '' : ::I18n.currency_label(#{datum}))" elsif column.name==:language and column.datatype == :string and column.limit <= 8 datum = "(#{datum}.blank? ? '' : ::I18n.translate('languages.'+#{datum}))" elsif column.name==:country and column.datatype == :string and column.limit <= 8 datum = "(#{datum}.blank? ? '' : (image_tag('countries/'+#{datum}.to_s+'.png')+' '+::I18n.translate('countries.'+#{datum})).html_safe)" elsif column.datatype == :string datum = "h("+datum+")" end else datum = 'nil' end code << "content_tag(:td, #{datum}, :class=>\"#{column_classes(column)}\"" code << ", :style=>"+style+"'" unless style[1..-1].blank? code << ")" when CheckBoxColumn.name code << "content_tag(:td," if nature==:body code << "hidden_field_tag('#{table.name}['+#{record}.id.to_s+'][#{column.name}]', 0, :id=>nil)+" code << "check_box_tag('#{table.name}['+#{record}.id.to_s+'][#{column.name}]', 1, #{column.options[:value] ? column.options[:value].to_s.gsub(/RECORD/, record) : record+'.'+column.name.to_s}, :id=>'#{table.name}_'+#{record}.id.to_s+'_#{column.name}')" else code << "''" end code << ", :class=>\"#{column_classes(column)}\")" when TextFieldColumn.name code << "content_tag(:td," if nature==:body code << "text_field_tag('#{table.name}['+#{record}.id.to_s+'][#{column.name}]', #{column.options[:value] ? column.options[:value].to_s.gsub(/RECORD/, record) : record+'.'+column.name.to_s}, :id=>'#{table.name}_'+#{record}.id.to_s+'_#{column.name}'#{column.options[:size] ? ', :size=>'+column.options[:size].to_s : ''})" else code << "''" end code << ", :class=>\"#{column_classes(column)}\")" when ActionColumn.name code << "content_tag(:td, "+(nature==:body ? column.operation(record) : "''")+", :class=>\"#{column_classes(column)}\")" else code << "content_tag(:td, ' ∅ '.html_safe)" end code << "+\n " # unless code.blank? end end if nature==:header code << "'#{menu_code(table)}'" else code << "content_tag(:td)" end return code end # Produces main menu code def menu_code(table) menu = "
" menu << "' + h(::I18n.translate('list.menu').gsub(/\'/,''')) + '" menu << "
" return menu end # Produces the code to create the header line using top-end menu for columns # and pagination management def header_code(table) code = "'" for column in table.columns code << "" code << "'+h(#{column.header_code})+'" code << "" code << "" end code << "#{menu_code(table)}" code << "'" return code end # Produces the code to create bottom menu and pagination def extras_code(table) code, pagination = nil, '' if table.paginate? current_page = "#{table.records_variable_name}_page" last_page = "#{table.records_variable_name}_last" pagination << "
" pagination << "' + ::I18n.translate('list.pagination.first') + '" pagination << "' + ::I18n.translate('list.pagination.previous') + '" x = '@@PAGE-NUMBER@@' y = '@@PAGE-COUNT@@' pagination << "'+::I18n.translate('list.page_x_on_y', :default=>'%{x} / %{y}', :x => '#{x}', :y =>'#{y}').html_safe.gsub('#{x}', ('').html_safe).gsub('#{y}', #{table.records_variable_name}_last.to_s) + '" pagination << "' + ::I18n.translate('list.pagination.next')+'" pagination << "' + ::I18n.translate('list.pagination.last')+'" pagination << "" pagination << "'+::I18n.translate('list.pagination.showing_x_to_y_of_total', :x => (#{table.records_variable_name}_offset + 1), :y => ((#{table.records_variable_name}_last==#{table.records_variable_name}_page) ? #{table.records_variable_name}_count : #{table.records_variable_name}_offset+#{table.records_variable_name}_limit), :total => #{table.records_variable_name}_count)+'" pagination << "
" code = "(#{table.records_variable_name}_last > 1 ? '
#{pagination}
' : '').html_safe" end return code end # Not used def columns_definition_code(table) code = table.columns.collect do |column| ":#{table.controller_method_name}, :column=>#{column.id.to_s.inspect})\}\\\" />" end.join return "\"#{code}\"" end # Finds all default styles for column def column_classes(column, without_id=false, without_interpolation=false) classes, conds = [], [] conds << [:sor, "list_params[:sort]=='#{column.id}'"] if column.sortable? conds << [:hidden, "list_params[:hidden_columns].include?('#{column.id}')"] if column.is_a? DataColumn classes << column.options[:class].to_s.strip unless column.options[:class].blank? classes << column.simple_id unless without_id if column.is_a? ActionColumn classes << :act elsif column.is_a? DataColumn classes << :col classes << DATATYPE_ABBREVIATION[column.datatype] classes << :url if column.options[:url].is_a?(Hash) classes << column.name if [:code, :color, :country].include? column.name.to_sym if column.options[:mode] == :download classes << :dld elsif column.options[:mode]||column.name == :email classes << :eml elsif column.options[:mode]||column.name == :website classes << :web end elsif column.is_a? TextFieldColumn classes << :tfd elsif column.is_a? CheckBoxColumn classes << :chk else classes << :unk end html = classes.join(' ').strip if conds.size > 0 if without_interpolation html << "' + " html << conds.collect do |c| "(#{c[1]} ? ' #{c[0]}' : '')" end.join(' + ') html << " + '" else html << conds.collect do |c| "\#\{' #{c[0]}' if #{c[1]}\}" end.join end end return html end end end ActiveList.register_renderer(:simple_renderer, ActiveList::SimpleRenderer)