# Kiss Form Field types. class Kiss class Form class HiddenField < Field; end class TextField < Field; end class TextAreaField < Field _attr_accessor :rows, :cols def initialize(*args) @_rows = 5 @_cols = 20 super(*args) end def element_html(attrs = {}) content_tag_html( 'textarea', value_string, attrs.merge( :rows => @_rows ||= 1, :cols => @_cols ||= 1 ) ) + tip_html(attrs) end end class PasswordField < Field def element_html(*args) input_tag_html(*args) end end class FileField < Field def element_html(attrs = {}) input_tag_html(attrs) + tip_html(attrs) end def get_file_name; end def get_file_data; end def require_value(enter_verb) p = param return add_error("Please choose #{label}") unless p && p[:type] end def validate require_value(nil) if @_required end end class SubmitField < Field def initialize(*args) @_save = false super(*args) end def element_html(*args) elements_html(*args).join(' ') end def elements_html(attrs = {}) @_options.map do |option| input_tag_html(attrs.merge( :value => value_to_s(option) )) end end end # ------ MultiChoiceField class MultiChoiceField < Field def initialize(*args, &block) @_options_display_transform = :to_s super(*args, &block) end def option_pairs pairs = if @_options_value_key if @_options_display_key.is_a?(Proc) @_options.map {|option| [ option[@_options_value_key], @_options_display_key.call(option) ]} else @_options.map {|option| [ option[@_options_value_key] || option.send(@_options_value_key), option[@_options_display_key] || option.send(@_options_display_key) ]} end else @_display_format = @_format @_options.map {|option| [ option, option ]} end pairs end def has_option_value?(v) !(@_options_value_key ? @_options.select {|o| value_to_s(o[@_options_value_key]) == v } : @_options.select {|o| value_to_s(o) == v } ).empty? end def validate if @_other && param == 'other' @_param = @_form.params[@_name+'.other'] end super('select') if @_value =~ /\S/ && !has_option_value?(@_value) add_error "Invalid selection" end end end class SelectField < MultiChoiceField def element_html(attrs = {}) return 'No options' unless @_options.size > 0 @_choose_here ||= 'Choose Here' placeholder_html = %Q() options_html = option_pairs.map do |option_value, option_display| option_value_string = value_to_s(option_value) selected = (value_string == option_value_string) ? ' selected' : '' %Q() end.join content_tag_html('select', placeholder_html + options_html, attrs) + other_field_html + tip_html(attrs) end end class RadioField < MultiChoiceField def element_html(attrs = {}) column_layout(elements_html(attrs)) + other_field_html + tip_html(attrs) end def elements_html(attrs = {}) option_pairs.map do |option_value, option_display| option_value_string = value_to_s(option_value) input_tag_html( attrs.merge( :type => 'radio', :value => option_value_string ), (value_string == option_value_string) ? 'checked' : '' ) + @_currency.to_s + display_to_s(option_display) end end end class BooleanField < RadioField def initialize(*args, &block) @_options = [[1, 'Yes'], [0, 'No']] super(*args, &block) end end # ------ MultiValueField class MultiValueField < MultiChoiceField def param @_form.params[@_name.to_s+'[]'] || [] end def validate begin @_value = param.map { |p| @_format.validate(p) } rescue Kiss::Format::ValidateError => e return add_error("#{e.message.capitalize}") end if @_value.empty? && @_required return add_error "Please select at least one #{@_label.downcase.singularize}" end if @_min_value_size && @_value.size < @_min_value_size return add_error "Please select at least #{@_min_value_size.of(@_label.downcase)}" end if @_max_value_size && @_value.size > @_max_value_size return add_error "Please select no more than #{@_max_value_size.of(@_label.downcase)}" end @_value.each do |v| unless has_option_value?(v) return add_error "Invalid selection" end end end def selected_option_values @_selected_option_values ||= @_value ? Hash[ *(@_value.map {|v| [value_to_s(v), true]}.flatten) ] : {} end end class CheckboxField < MultiValueField def element_html(attrs = {}) hidden_options = @_hidden_join ? input_tag_html( :type => 'hidden', :name => "#{@_name}_options", :value => option_pairs.map {|option_value, option_display| value_to_s(option_value) }.join(@_hidden_join) ) : '' column_layout(elements_html(attrs)) + other_field_html + hidden_options + tip_html(attrs) end def elements_html(attrs = {}) name = @_name.to_s+'[]' option_pairs.map do |option_value, option_display| option_value_string = value_to_s(option_value) input_tag_html( attrs.merge( :name => name, :value => option_value_string ), selected_option_values[option_value_string] ? 'checked' : '' ) + @_currency.to_s + display_to_s(option_display) end end end class MultiSelectField < MultiValueField def element_html(attrs = {}) options_html = option_pairs.map do |option_value, option_display| option_value_string = value_to_s(option_value) selected = selected_option_values[option_value_string] ? ' selected' : '' %Q() end.join content_tag_html( 'select', options_html, attrs, 'multiple' ) end end # not implemented yet: MultiTextField, end end