#-- # Copyright (c) 2012+ Damjan Rems # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ ########################################################################### # DrgcmsFormFields module contains definitions of classes used for # rendering data entry fields on DRG CMS forms. # # Every data entry field type written in lowercase in form must have its class # defined in CamelCase in DrgcmsFormFields module. # # Each class must have at least render method implemented. All classes can # inherit from DrgcmsField class which acts as abstract template class and implements # most of surrounding code for creating custom DRG CMS form field. # # Render method must create html and javascript code which must be # saved to internal @html and @js variables. Field code is then retrived by accessing # these two internal variables. # # Example. How the field code is generated in form renderer: # klas_string = yaml['type'].camelize # if DrgcmsFormFields.const_defined?(klas_string) # check if field type class is defined # klas = DrgcmsFormFields.const_get(klas_string) # field = klas.new(self, @record, options).render # javascript << field.js # html << field.html # end # # Example. How to mix DRG CMS field code in Rails views: #
User: # <%= # opts = {'name' => 'user', 'eval' => "dc_choices4('dc_user','name')", # 'html' => { 'include_blank' => true } } # dt = DrgcmsFormFields::Select.new(self, {}, opts).render # (dt.html + javascript_tag(dt.js)).html_safe # %>
########################################################################### module DrgcmsFormFields ########################################################################### # Template method for DRG CMS form field definition. This is abstract class with # most of the common code for custom form field already implemented. ########################################################################### class DrgcmsField attr_reader :js attr_reader :css #################################################################### # DrgcmsField initialization code. # # Parameters: # [parent] Controller object. Controller object from where object is created. Usually self is send. # [record] Document object. Document object which holds fields data. # [yaml] Hash. Hash object holding field definition data. # # Returns: # Self #################################################################### def initialize( parent, record, yaml ) @parent = parent @record = record @yaml = yaml @form = parent.form @yaml['html'] ||= {} # set readonly field @readonly = (@yaml and @yaml['readonly']) || (@form and @form['readonly']) @yaml['html']['readonly'] = true if @readonly # assign size to html element if not already there @yaml['html']['size'] ||= @yaml['size'] if @yaml['size'] @html = '' @js = '' @css = set_css_code @yaml['css'] self end #################################################################### # Returns html code together with CSS code. #################################################################### def html @html end #################################################################### # Wrapper for i18 t method, with some spice added. If translation is not found English # translation value will be returned. And if still not found default value will be returned if passed. # # Parameters: # [key] String. String to be translated into locale. # [default] String. Value returned if translation is not found. # # Example: # t('translate.this','Enter text for ....') # # Returns: # String. Translated text. #################################################################### def t(key, default='') c = I18n.t(key) if c.match( 'translation missing' ) c = I18n.t(key, locale: 'en') # Still not found. Return default if set c = default unless default.blank? end c end #################################################################### # Standard code for returning readonly field. #################################################################### def ro_standard(value=nil) if value.nil? value = if @yaml['html']['value'] @yaml['html']['value'] else @record.respond_to?(@yaml['name']) ? @record.send(@yaml['name']) : nil end end #@html << (value.blank? ? '' : "
#{value}
") @html << %(
#{value}
) self end #################################################################### # Set initial value of the field when initial value is set in url parameters.. # # Example: Form has field named picture. Field can be initialized by # setting value of param p_picture. # params['p_picture'] = '/path/to_picture' # # When multiple initial values are assigned it is more convinient to assign them # through flash object. # flash[:record] = {} # flash[:record]['picture'] = '/path/to_picture' #################################################################### def set_initial_value(opt1 = 'html', opt2 = 'value') @yaml['html'] ||= {} value_send_as = 'p_' + @yaml['name'] if @parent.params[value_send_as] @yaml[opt1][opt2] = @parent.params[value_send_as] elsif @parent.flash[:record] and @parent.flash[:record][@yaml['name']] @yaml[opt1][opt2] = @parent.flash[:record][@yaml['name']] end set_default_value(opt1, opt2) if @yaml['default'] end #################################################################### # Will set default value #################################################################### def set_default_value(opt1, opt2) return if @yaml[opt1][opt2].present? return if @record && @record[@yaml['name']].present? @yaml[opt1][opt2] = if @yaml['default'].class == Hash eval(@yaml['default']['eval']) else @yaml['default'] end end #################################################################### # Returns style html code for DRGForm object if style directive is present in field definition. # Otherwise returns empty string. # # Style may be defined like: # style: # height: 400px # width: 800px # padding: 10px 20px # # or # # style: "height:400px; width:800px; padding: 10px 20px;" # # Style directive may also be defined under html directive. # html: # style: # height: 400px # width: 800px # # #################################################################### def set_style() style = @yaml['html']['style'] || @yaml['style'] case when style.nil? then '' when style.class == String then "style=\"#{style}\"" when style.class == Hash then value = style.to_a.inject([]) {|r,v| r << "#{v[0]}: #{v[1]}" }.join(';') "style=\"#{value}\"" else '' end end #################################################################### # DEPRECATED! # # Returns css code for the field if specified. It replaces all occurences of '# ' # with field name id, as defined on form. #################################################################### def __css_code return '' if @css.blank? @css.gsub!('# ',"#td_record_#{@yaml['name']} ") "\n" end #################################################################### # Sets css code for the field if specified. It replaces all occurences of '# ' # with field name id, as defined on form. #################################################################### def set_css_code(css) return '' if css.blank? css.gsub!('# ',"#td_record_#{@yaml['name']} ") if css.match('# ') css end #################################################################### # Will return ruby hash formated as javascript string which can be used # for passing parameters in javascript code. # # Parameters: # [Hash] Hash. Ruby hash parameters. # # Form example: As used in forms # options: # height: 400 # width: 800 # toolbar: "'basic'" # # => "height:400, width:800, toolbar:'basic'" # # Return: # String: Options formated as javascript options. # #################################################################### def hash_to_options(hash) hash.to_a.inject([]) {|r,v| r << "#{v[0]}: #{v[1]}" }.join(',') end #################################################################### # Checks if field name exists in document and alters record parameters if necesary. # Method was added after fields that do not belong to current edited document # were added to forms. Valid nonexisting form field names must start with underscore (_) letter. # # Return: # String: 'record' or '_record' when valid nonexisting field is used #################################################################### def record_text_for(name) (!@record.respond_to?(name) and name[0,1] == '_') ? '_record' : 'record' end ########################################################################### # Default get_data method for retrieving data from parameters. Class method is called # for every entry field defined on form before field value is saved to database. # # Parameters: # [params] Controllers params object. # [name] Field name # # Most of classes will use this default method which returns params['record'][name]. # When field data is more complex class should implement its own get_data method. ########################################################################### def self.get_data(params, name) params['record'][name] end end end