module Zena
module Use
module Forms
module ViewMethods
# Create a new instance of the given class name
def new_instance(class_name, params = {})
return nil unless klass = Node.get_class(class_name, :create => true)
klass.new_instance(Node.transform_attributes(params))
end
def make_checkbox(node, opts)
if relation_name = opts[:role]
values, attribute = opts[:list], opts[:attr]
relation_proxy = node.relation_proxy(relation_name)
return nil unless values && relation_proxy
res = []
role = relation_proxy.other_role
if relation_proxy.unique?
current_value = relation_proxy.other_id
values.each do |value|
res << (" " : '/> ') +
"#{value.prop[attribute]}")
end
res << " #{_('none')}"
else
current_values = relation_proxy.other_ids
res << ""
values.each do |value|
res << ("
" : '/> ') +
"#{value.prop[attribute]}
")
end
end
res.join('')
else
# literal values
list, name, selected = opts[:list], opts[:name], opts[:selected]
show = opts[:show] || list
if selected.kind_of?(Array)
selected = selected.map(&:to_s)
name = "node[#{name}][]"
else
selected = [selected.to_s]
name = "node[#{name}]"
end
res = []
if default = opts[:default]
default = fquote default.to_s
else
default = ''
end
res << ""
type = opts[:type] || 'checkbox'
list.each_with_index do |value, i|
res << (" " : '/> ') +
"#{show[i]}")
end
res.join('')
end
end
# Find a params value from an input name (q[foo] ==> safe params[q][foo])
def param_value(name)
# q[foo.bar][xxx]
list = name.gsub(']','').split('[')
# q foo.bar xxx
base = params
while true
key = list.shift
if base.kind_of?(Hash)
base = base[key]
else
return nil
end
break if list.empty?
end
base
end
def profile_users
secure(User) {User.find_all_by_is_profile(true) } || []
end
end # ViewMethods
module ZafuMethods
# Enter the context of a newly created object
def r_new
return parser_error("missing 'klass' parameter") unless class_name = @params[:klass]
return parser_error("invalid 'klass' parameter") unless klass = get_class(class_name)
return parser_error("invalid 'klass' parameter (not a Node)") unless klass <= Node
res = []
keys = {:klass => 'this.klass', :parent_id => "#{node(Node)}.zip"}
@params.each do |key, value|
next if key == :klass
# TODO: maybe it would be safer to check with [:"key="] and change safe_property to
# authorize both ?
next unless type = klass.safe_method_type([key.to_s])
# Store how to access current value to show hidden field in form.
keys[key] = "this.#{type[:method]}"
code = RubyLess.translate(self, value)
if code.klass == type[:class]
res << ":#{key} => #{code}"
else
out parser_error("invalid type for '#{key}' (found #{code.klass}, expected #{type[:class]})")
end
end
if res == []
method = "new_instance(#{class_name.inspect})"
else
method = "new_instance(#{class_name.inspect}, #{res.join(', ')})"
end
expand_with_finder(
:method => method,
:class => klass,
:nil => true,
:new_keys => keys
)
end
def r_errors
# Very basic for the moment
"<%= error_messages_for(#{node.form_name}, :object => #{node}) %>"
end
def make_input(form_helper, name, type, textarea = false)
if type == Time
code = RubyLess.translate(self, "this.#{name}")
"<%= date_box(#{node}, 'node[#{name}]', :value => #{code}) %>"
elsif textarea
"<%= #{form_helper}.text_area :#{name}, :id => '#{node.dom_prefix}_#{name}' %>"
else
"<%= #{form_helper}.text_field :#{name}, :id => '#{node.dom_prefix}_#{name}' %>"
end
end
def make_form
if !@context[:make_form] || node.list_context? || @context[:form_helper].blank?
return super
else
form_helper = @context[:form_helper]
end
if %W{link show}.include?(method) || method == 'zazen' || (name = method[/zazen\(\s*(\w+)\s*\)/,1])
name ||= @params[:attr] || @params[:date] || 'title'
textarea = method =~ /zazen/
elsif type = node.klass.safe_method_type([method])
name = method
end
if name
type ||= node.klass.safe_method_type([name])
# do we have a property ?
if type && (node.real_class.column_names.include?(name) || node.klass.column_names.include?(name))
# create an input field
out make_input(form_helper, name, type[:class], textarea)
else
# ignore
out ''
end
else
super
end
end
def form_options
opts = super
dom_name = node.dom_prefix
opts[:form_helper] = 'f'
if upd = @params[:update]
if target = find_target(upd)
@context[:template_url] = target.template_url
end
end
if template_url = @context[:template_url]
# Ajax
if edit_or_cancel = descendant('cancel') || descendant('edit')
if cancel_text = edit_or_cancel.params[:cancel] ||
(edit_or_cancel.method == 'cancel' && edit_or_cancel.params[:text])
elsif cancel_text = edit_or_cancel.params[:tcancel] ||
(edit_or_cancel.method == 'cancel' && edit_or_cancel.params[:t])
cancel_text = RubyLess.translate(self, "t(%Q{#{cancel_text}})")
if cancel_text.literal
cancel_text = cancel_text.literal
else
cancel_text_ruby = cancel_text
cancel_text = "<%= #{cancel_text} %>"
end
end
cancel_pre = ''
cancel_post = ''
else
cancel_pre = "
"
cancel_post = "
"
end
cancel_text ||= _('btn_x')
cancel_text_ruby ||= cancel_text.inspect
if @context[:in_add]
# Inline form used to create new elements: set values to '' and 'parent_id' from context
opts[:id] = "#{node.dom_prefix}_0"
opts[:form_tag] = "<% remote_form_for(:#{node.form_name}, #{node}, :url => #{node.form_name.pluralize}_path, :html => {:id => \"#{dom_name}_form_t\"}) do |f| %>"
opts[:form_cancel] = "#{cancel_pre}#{cancel_text}#{cancel_post}\n"
else
# Saved form
if @markup.tag == 'table'
# the normal id goes to the form wrapping the table
opts[:id] = "#{node.dom_prefix}_tbl"
str_form_id = "\#{ndom_id(#{node})}"
else
opts[:id] = "<%= ndom_id(#{node}) %>"
str_form_id = "\#{ndom_id(#{node})}_form_t"
end
form_id ||= "#{node.dom_prefix}_form_t"
opts[:form_tag] = %Q{
<% remote_form_for(:#{node.form_name}, #{node}, :url => #{node}.new_record? ? #{node.form_name.pluralize}_path : #{node.form_name}_path(#{node}.zip), :html => {:method => #{node}.new_record? ? :post : :put, :id => \"#{str_form_id}\"}) do |f| %>
}
opts[:form_cancel] = %Q{
<% if #{node}.new_record? %>
#{cancel_pre}#{cancel_text}#{cancel_post}
<% else %>
#{cancel_pre}<%= link_to_remote(#{cancel_text_ruby}, :url => #{node.form_name}_path(#{node}.zip) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=\#{params[:dom_id]}#{@context[:has_link_id] ? "&link_id=\#{#{node}.link_id}" : ''}\", :method => :get) %>#{cancel_post}
<% end %>
}
end
else
# no ajax
if descendants('errors')
error_messages = ''
else
error_messages = r_errors + "\n"
end
html_id = "#{node.dom_prefix}_form_t".inspect
if descendant('upload_field')
uuid = UUIDTools::UUID.random_create.to_s.gsub('-','')
set_context_var('upload', 'uuid', uuid)
upload_html = ", :multipart => true, :onsubmit => %Q{submitUploadForm(#{html_id}, '#{uuid}');}"
upload_url = "'#{Zena::Use::Upload::UPLOAD_KEY}' => '#{uuid}'"
end
opts[:form_tag] = %Q{
<% form_for(:#{node.form_name}, #{node}, :url => #{node}.new_record? ? #{node.form_name.pluralize}_path(#{upload_url}) : #{node.form_name}_path(#{node}.zip#{upload_url ? ", #{upload_url}" : ""}), :html => {:method => #{node}.new_record? ? :post : :put, :id => #{html_id}#{upload_html}}) do |f| %>
#{error_messages}}
end
opts
end
def form_hidden_fields(opts)
dom_name = node.dom_prefix || dom_name
hidden_fields = super
add_params = @context[:add] ? @context[:add].params : {}
set_fields = []
@markup.params[:class] ||= 'form'
(descendants('input') + descendants('select')).each do |tag|
set_fields << "#{node.form_name}[#{tag.params[:name]}]"
end
if (descendants('input') || []).detect {|elem| elem.params[:type] == 'submit'}
# has submit
else
# Hidden submit for Firefox compatibility
hidden_fields['submit'] = [""]
end
if template_url = @context[:template_url]
# Ajax
hidden_fields['link_id'] = "<%= #{node}.link_id %>" if @context[:has_link_id] && node.will_be?(Node)
f = @method == 'form_tag' ? ancestor('form') : self
if upd = f && f.params[:update]
if target = find_target(upd)
hidden_fields['u_url'] = target.template_url
hidden_fields['udom_id'] = upd # target.node.dom_prefix ? (but target.node is not set yet...)
# hidden_fields['u_id'] = "<%= #{@context[:parent_node]}.zip %>" if @context[:in_add]
hidden_fields['s'] = "<%= start_node_zip %>"
end
# elsif (block = ancestor('block')) && node.will_be?(DataEntry)
# # updates template url
# hidden_fields['u_url'] = block.template_url
# hidden_fields['udom_id'] = block.erb_dom_id
end
hidden_fields['t_url'] = template_url
# This is a hack to fix wrong dom_prefix in drop+add.
#erb_dom_id = @context[:saved_template] ? "<%= ndom_id(#{node}, false) %>" : (@context[:dom_prefix] || node.dom_prefix)
if @context[:saved_template]
hidden_fields['dom_id'] = erb_dom_id = "<%= ndom_id(#{node}, false) %>"
else
hidden_fields['dom_id'] = erb_dom_id = node.dom_prefix
end
if node.will_be?(Comment)
# FIXME: the "... || '@node'" is a hack and I don't understand why it's needed...
hidden_fields['node_id'] = "<%= #{node.get(Node) || '@node'}.zip %>"
elsif node.will_be?(DataEntry)
return parser_error("Missing :data_root in context (internal error)") unless data_root = @context[:data_root]
hidden_fields["data_entry[#{data_root}_id]"] = "<%= #{@context[:in_add] ? node(Node) : "#{node}.#{data_root}"}.zip %>"
end
if add_block = @context[:add]
params = add_block.params
hidden_fields['zadd'] = 'true'
[:after, :before, :top, :bottom].each do |sym|
if value = params[sym]
hidden_fields['position'] = sym.to_s
if value == 'self'
if sym == :before
hidden_fields['reference'] = "#{erb_dom_id}_add"
else
hidden_fields['reference'] = "#{erb_dom_id}_0"
end
else
hidden_fields['reference'] = value
end
break
end
end
if params[:done]
if params[:done] == 'focus'
hidden_fields['done'] = "'$(\"#{erb_dom_id}_form_t\").focusFirstElement();'"
else
done = RubyLess.translate_string(self, params[:done])
end
elsif params[:focus]
hidden_fields['done'] = "'$(\"#{erb_dom_id}_#{params[:focus]}\").focus();'"
end
else
# ajax form, not in 'add'
done = RubyLess.translate_string(self, @params[:done])
end
if done
if done.literal
done = done.literal
else
done = "<%= fquote #{done} %>"
end
hidden_fields['done'] = done
end
elsif upd = @params.delete(:preview)
hidden_fields['t_url'] = template_url(upd)
hidden_fields['dom_id'] = upd
hidden_fields['s'] = "<%= start_node_zip %>"
loading = @params[:loading]
loading = 'Zena.loading' if loading == 'true'
out "<% filter_form(#{node}, \"#{dom_name}_form_t\", #{loading.inspect}, '#{upd}') %>"
else
# no ajax
cancel = "" # link to normal node ?
end
if node.will_be?(Node) && (@params[:klass] || @context[:klass])
hidden_fields['node[klass]'] = @params[:klass] || @context[:klass].name
end
if node.will_be?(Node) && @params[:mode]
hidden_fields['mode'] = @params[:mode]
end
hidden_fields['node[v_status]'] = Zena::Status::Pub.to_s if add_params[:publish] || auto_publish_param || @context[:publish_after_save]
# All default values set in the field should at least appear as hidden fields
if new_keys = node.opts[:new_keys]
input_keys = (
(descendants('input') || []).map {|e| e.params[:name]} +
hidden_fields.keys.map do |e|
if e =~ /.*\[(.*)\]/
$1.to_sym
else
nil
end
end
).compact.uniq
new_keys.each do |key, value|
# Security: make sure value does not come from user input !
# TINT !
next if input_keys.include?(key) || value.nil?
hidden_fields["node[#{key}]"] = "<%= #{value.sub(/^this\./, "#{node}.")} %>"
end
end
# Read @params
add_params.merge(@params).each do |key, value|
# r_add params
next if [:after, :before, :top, :bottom, :focus, :publish,
# r_form params
:klass, :done, :on, :update,
# r_each params (make_form)
:join, :alt_class].include?(key)
code = ::RubyLess.translate(self, value)
if code.literal.kind_of?(String) || code.literal.kind_of?(Number)
hidden_fields[key.to_s] = "#{code.literal}"
else
hidden_fields[key.to_s] = "<%= #{code} %>"
end
end
hidden_fields.reject! do |k,v|
# There is an explicit field for this key, remove hidden value
set_fields.include?(k)
end
hidden_fields
end
def r_upload_field
"<%= upload_field(:uuid => #{get_context_var('upload', 'uuid').inspect}, :dom => #{node.dom_prefix.inspect}) %>"
end
def r_textarea
html_attributes, attribute = get_input_params()
erb_attr = html_attributes.delete(:erb_attr)
value = html_attributes.delete(:value)
return parser_error('Missing name.') unless attribute || html_attributes[:name]
@markup.tag = 'textarea'
@markup.set_dyn_params(html_attributes)
if @blocks == [] || @blocks == ['']
if @context[:in_add]
value = ''
end
else
value = expand_with
end
res = @markup.wrap(value)
extract_label(res, attribute || erb_attr)
end
#
#
#
# TODO: optimization (avoid loading full AR to only use [id, name])
def r_select
html_attributes, attribute = get_input_params()
erb_attr = html_attributes.delete(:erb_attr)
# TEMPORARY HACK UNTIL WE FIX get_input_params to return a single hash with
# {:html => { prepared html attributes }, :raw => {:value => '..', :name => '..', :param => '..'}}
if param = @params[:param]
selected = "param_value(#{param.inspect}).to_s"
attribute = param
else
return parser_error("missing name") unless attribute
# {:value=>"<%= fquote((@node.prop['settings'] ? @node.prop['settings'][\"foo\"] : nil)) %>", :name=>"node[settings][foo]"}
# "settings_foo"
if selected = @params[:value] || @params[:selected]
selected = ::RubyLess.translate(self, selected)
unless selected.klass <= String
selected = "#{selected}.to_s"
end
elsif @context[:in_filter]
selected = "param_value(#{attribute.inspect}).to_s"
elsif %w{parent_id}.include?(attribute)
selected = "#{node}.parent_zip.to_s"
elsif attribute == 'copy_id'
selected = 'nil'
elsif attribute =~ /^(.*)_id$/
# relation
selected = "#{node}.rel[#{$1.inspect}].other_zip.to_s"
elsif selected = html_attributes[:value]
if selected =~ /\A<%= .*?\((.+)\)\s*%>/
# remove <%= %>
selected = "#{$1}.to_s"
else
selected = selected.inspect
end
else
# FIXME: This would not work for a [asdf][asdf] hash property type...
selected = ::RubyLess.translate(self, "this.#{attribute}")
end
end
if @context[:in_filter] || @params[:param]
html_attributes[:name] = attribute
end
html_attributes.delete(:value)
select_tag = Zafu::Markup.new('select', html_attributes)
res = if klass = @params[:root_class]
class_opts = ''
class_opts << ", :without => #{@params[:without].inspect}" if @params[:without]
tprefix = @params[:tprefix] || @params[:name] || @params[:param]
# do not use 'selected' if the node is not new
options_list = Node.classes_for_form(:class => klass, :without => @params[:without], :class_attr => @params[:attr] || 'name')
if !tprefix.blank? && tprefix != 'false'
options_list.map! do |e|
if e[0] =~ /^([^a-zA-Z]*)(.*)$/
name = "#{tprefix}_#{$2}"
t = trans(name)
t = $2 if t == name
[$1 + t, e[1]]
else
e
end
end
end
select_tag.wrap "<%= options_for_select(#{options_list.inspect}, #{selected}) %>"
elsif @params[:type] == 'time_zone'
#
select_tag.wrap "<%= options_for_select(TZInfo::Timezone.all_identifiers, #{selected}) %>"
elsif @params[:type] == 'profile'
#
select_tag.wrap "<%= options_for_select(profile_users.map{|u| u.login}.sort, #{selected}) %>"
elsif options_list = get_options_for_select
select_tag.wrap "<%= options_for_select(#{options_list}, #{selected}) %>"
else
parser_error("missing 'nodes', 'root_class' or 'values'")
end
extract_label(res, attribute || erb_attr)
end
def r_input(skip_col = false)
html_attributes, attribute = get_input_params()
erb_attr = html_attributes.delete(:erb_attr)
# TODO: get attribute type from get_input_params
if !skip_col && node.will_be?(Column) && !@params[:type]
# hack to change @params
out "<% if #{node}.ptype == :string -%>"
out r_textarea
out "<% elsif #{node}.ptype == :datetime -%>"
res = "<%= date_box(#{node(Node)}, %Q{node[\#{#{node}.name}]}, :value => #{node(Node)}.prop[#{node}.name]) %>"
out extract_label(res, erb_attr)
out "<% else -%>"
out r_input(true)
out "<% end -%>"
return
end
res = case @params[:type]
when 'select' # FIXME: why is this only for classes ?
out parser_error("please use [select] here")
r_select
when 'date_box', 'date'
return parser_error("date_box without name") unless attribute
if code = @params[:value]
code = ::RubyLess.translate(self, code)
elsif code = html_attributes[:value]
if code =~ /\A<%= .*?\((.+)\)\s*%>/
# remove <%= %>
code = $1
else
code = code.inspect
end
else
code = ::RubyLess.translate(self, "this.#{attribute}")
end
value = code # @context[:in_add] ? "''" : code
html_params = [':size => 15']
[:style, :class, :onclick, :size, :time, :id, :onUpdate].each do |key|
html_params << ":#{key} => #{@params[key].inspect}" if @params[key]
end
if !@params[:id] and node.dom_prefix
html_params << ":id=>\"#{node.dom_id(:erb => false)}_#{attribute}\""
end
"<%= date_box(#{node}, #{html_attributes[:name].inspect}, :value => #{value}, #{html_params.join(', ')}) %>"
when 'id'
return parser_error("select id without name") unless attribute
name = "#{attribute}_id" unless attribute[-3..-1] == '_id'
input_id = @context[:erb_dom_id] ? ", :input_id =>\"#{erb_dom_id}_#{attribute}\"" : ''
# FIXME: pass object
"<%= select_id('#{node.form_name}', #{attribute.inspect}#{input_id}) %>"
when 'time_zone'
out parser_error("please use [select] here")
r_select
when 'submit'
@markup.tag = 'input'
@markup.set_param(:type, @params[:type])
@markup.set_param(:text, @params[:text]) if @params[:text]
@markup.set_params(html_attributes)
@markup.done = false
wrap('')
else
# 'text', 'hidden', 'checkbox', ...
return parser_error('Missing name.') unless attribute || html_attributes[:name]
if @markup.tag != 'input'
# Do not rewrite tag, use another one.
markup = Zafu::Markup.new('input')
else
markup = @markup
end
markup.tag = 'input'
markup.set_param(:type, @params[:type] || 'text')
checked = html_attributes.delete(:checked)
markup.set_dyn_params(html_attributes)
markup.append_attribute checked if checked
markup.done = false
if markup == @markup
wrap('')
else
markup.wrap('')
end
end
if @params[:type] == 'checkbox'
out ""
end
extract_label(res, attribute || erb_attr)
end
# "
def r_checkbox
nodes = @params[:nodes]
values = @params[:values]
return parser_error("missing 'nodes' or 'values'") unless nodes || values
if values
return parser_error("missing attribute 'name'") unless name = @params[:name]
# parse literal values
opts = [":name => #{name.inspect}", ":list => #{values.split(',').map(&:strip).inspect}"]
if show_values = @params[:show]
opts << ":show => #{show_values.split(',').map(&:strip).inspect}"
elsif show_values = @params[:tshow]
opts << ":show => #{translate_list(show_values).inspect}"
else
opts << ":show => #{translate_list(values, @params[:tprefix] || name).inspect}"
end
meth = RubyLess.translate(self, "this.#{name}")
opts << ":selected => #{meth}"
if default = @params[:default]
opts << ":default => #{default.inspect}"
end
if type = @params[:type]
opts << ":type => #{type.inspect}"
end
attribute = name
res = "<%= make_checkbox(#{node}, #{opts.join(', ')}) %>"
else
if name = @params[:name]
if name =~ /(.*)_ids?\Z/
role = $1
else
role = name
end
else
role = @params[:role]
end
return parser_error("missing 'role'") unless role
# nodes
meth = role.singularize
if nodes =~ /^\d+\s*($|,)/
values = nodes.split(',').map{|v| v.to_i}
finder = "secure(Node) { Node.all(:conditions => 'zip IN (#{values.join(',')})') }"
else
return unless finder = build_finder(:all, nodes, @params)
return parser_error("invalid class (#{finder[:class]})") unless finder[:class].first <= Node
finder = finder[:method]
end
attribute = @params[:attr] || 'title'
res = "<%= make_checkbox(#{node}, :list => #{finder}, :role => #{meth.inspect}, :attr => #{attribute.inspect}) %>"
end
extract_label(res, attribute)
end
def r_radio
@params[:type] = 'radio'
r_checkbox
end
# Parse params to extract everything that is relevant to building input fields.
# TODO: refactor and pass the @markup so that attributes are added directly
# TODO: get attribute type in get_input_params (safe_method_type)
def get_input_params(params = @params)
res = Zafu::OrderedHash.new
if name = (params[:param] || params[:name] || params[:date])
res[:name] = name
if params[:param]
if name =~ /^[a-z_]+$/
sub_attr_ruby = "params[:#{name}]"
else
sub_attr_ruby = "param_value(#{name.inspect})"
end
else
# build name
if res[:name] =~ /\A([\w_]+)\[(.*?)\]/
# Sub attributes are used with tags or might be used for other features. It
# enables things like 'tagged[foo]'
attribute, sub_attr = $1, $2
else
attribute = res[:name]
end
if sub_attr
res[:name] = "#{node.form_name}[#{attribute}][#{sub_attr}]"
else
res[:name] = "#{node.form_name}[#{attribute}]"
end
end
if value = params[:value]
# On refactor, use append_markup_attr(markup, key, value)
value = RubyLess.translate_string(self, value)
if value.literal
res[:value] = form_quote(value.literal.to_s)
else
res[:value] = "<%= fquote(#{value}) %>"
end
elsif params[:param]
res[:value] = "<%= fquote(#{sub_attr_ruby}) %>"
end
if sub_attr
type = node.klass.safe_method_type([attribute], node)
if sub_attr_ruby = RubyLess.translate(self, %Q{this.#{attribute}[#{sub_attr.inspect}]})
res[:value] ||= "<%= fquote(#{sub_attr_ruby}) %>"
end
elsif attribute && type = node.klass.safe_method_type([attribute], node)
res[:value] ||= "<%= fquote(#{node}.#{type[:method]}) %>"
end
if sub_attr && params[:type] == 'checkbox' && !params[:value]
# Special case when we have a sub_attribute: default value for "tagged[foobar]" is "foobar"
res[:value] = sub_attr
end
elsif node.will_be?(Column)
res[:erb_attr] = "<%= #{node}.name %>"
res[:name] = "node[<%= #{node}.name %>]"
res[:value] = "<%= fquote #{node(Node)}.prop[#{node}.name] %>"
end
if params[:id]
res[:id] = params[:id]
elsif base = @context[:form_prefix]
res[:id] = "#{base}_#{attribute}"
end
if params[:type] == 'checkbox' && sub_attr_ruby
if value = params[:value]
res[:checked] = "<%= #{sub_attr_ruby} == #{value.inspect} ? \" checked='checked'\" : '' %>"
else
res[:checked] = "<%= #{sub_attr_ruby}.blank? ? '' : \" checked='checked'\" %>"
end
end
params.each do |k, v|
if [:size, :style, :class].include?(k) || k.to_s =~ /^data-/
res[k] = params[k]
end
end
if sub_attr
return [res, "#{attribute}_#{sub_attr}"]
else
return [res, attribute]
end
end
# TODO: add parent_id into the form !
# TODO: add if method == put
# FIXME: use or
=begin
form << "<%= error_messages_for(#{node}) %>"
@blocks = blocks_bak if blocks_bak
@html_tag_done = false
@html_tag_params.merge!(id_hash)
out render_html_tag(res)
=end
def r_crop
return parser_error("Invalid node type #{node.klass} (should be an Image).") unless node.will_be?(Image)
@markup.tag ||= 'div'
node.dom_prefix = dom_name
@markup.set_id(node.dom_id(:list => false))
dom = node.dom_id(:erb => false, :list => false)
out %Q{<%= render :partial => 'documents/crop', :locals => {:node => #{node(Node)}, :img_id => "img#{dom}"} %>}
out %Q{<% js_data << %Q{new Zena.Div_editor("img#{dom}", 'posx', 'posy', 'width', 'height', \#{#{node}.width / #{node}.width(Iformat['edit']).to_f}, Element.viewportOffset('#{dom}').left, Element.viewportOffset('#{dom}').top);} %>}
end
protected
# Get current attribute in forms
def node_attribute(attribute)
node_attribute = ::RubyLess.translate(node.klass, attribute)
"#{node}.#{node_attribute}"
rescue ::RubyLess::NoMethodError
if node.will_be?(Node)
"#{node}.prop[#{attribute.inspect}]"
else
'nil'
end
end
# Set auto publish parameter value
def auto_publish_param(in_string = false)
if in_string
%w{true force}.include?(@params[:publish]) ? "&publish=#{@params[:publish]}" : ''
else
@params[:publish]
end
end
# Return options for [select] tag.
def get_options_for_select
if nodes = @params[:nodes]
# TODO: dry with r_checkbox
klass = Node
if nodes =~ /^\d+\s*($|,)/
# ids
# TODO: optimization generate the full query instead of using secure.
nodes = nodes.split(',').map{|v| v.to_i}
nodes = "(secure(Node) { Node.find(:all, :conditions => 'zip IN (#{nodes.join(',')})') })"
else
# relation
begin
finder = build_finder(:all, nodes, @params)
klass = finder[:class].first
rescue ::QueryBuilder::Error => err
out parser_error(err.message)
return nil
end
return parser_error("invalid class (#{klass})") unless klass <= Node
nodes = finder[:method]
end
set_attr, show_attr = nil
with_context(:node => node.move_to('r', klass)) do
set_attr = ::RubyLess.translate(self, @params[:attr] || 'id')
show_attr = ::RubyLess.translate(self, @params[:show] || 'title')
end
if @params[:blank] != 'false'
options_list = "[['', '']] + "
else
options_list = ""
end
options_list = "#{options_list}(#{nodes} || []).map{|r| [#{show_attr}, #{set_attr}.to_s]}"
elsif values = @params[:values]
options_list = values.split(',').map(&:strip)
if show = @params[:show]
show_values = show.split(',').map(&:strip)
elsif show = @params[:tshow]
show_values = translate_list(show)
else
tprefix = @params[:tprefix] || @params[:name] || @params[:param]
tprefix = tprefix.gsub('[','_').gsub(']','')
if tprefix == 'false'
tprefix = ''
else
tprefix = "#{tprefix}_"
end
show_values = options_list.map do |v|
t = trans("#{tprefix}#{v}")
if t == tprefix
''
else
t
end
end
end
if show_values
options_list.each_index do |i|
options_list[i] = [show_values[i], options_list[i]]
end
end
options_list.inspect
elsif code = @params[:eval]
ruby = ::RubyLess.translate(self, code)
if ruby.klass.kind_of?(Array)
if ruby.klass.first <= String
ruby
else
return parser_error("cannot extract values from eval (not a String list: [#{ruby.klass.first}])")
end
elsif ruby.klass <= String
if ruby.could_be_nil?
ruby = "(#{ruby} || '')"
else
ruby = "(#{ruby})"
end
dict = get_context_var('set_var', 'dictionary')
if dict && dict.klass <= ::Zena::Use::I18n::TranslationDict
trans = "#{dict}.get"
else
trans = "trans"
end
ruby = "#{ruby}.split(',').map(&:strip).map {|e| [#{trans}(e), e]}"
else
return parser_error("invalid eval: should return an Array or String (found #{ruby.klass})")
end
end
end
# Return the default field that will receive focus on form display.
def default_focus_field
if (input_fields = descendants('input')) != []
input_fields.first.params[:name]
elsif (show_fields = descendants('show')) != []
show_fields.first.params[:attr]
elsif node.will_be?(Node)
'title'
else
'text'
end
end
end # ZafuMethods
end # Forms
end # Use
end # Zena