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 = ""
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 << ""
code = "(#{table.records_variable_name}_last > 1 ? '' : '').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)