module ActiveScaffold module Helpers # All extra helpers that should be included in the View. # Also a dumping ground for uncategorized helpers. module ViewHelpers include ActiveScaffold::Helpers::IdHelpers include ActiveScaffold::Helpers::AssociationHelpers include ActiveScaffold::Helpers::PaginationHelpers include ActiveScaffold::Helpers::ListColumnHelpers include ActiveScaffold::Helpers::ShowColumnHelpers include ActiveScaffold::Helpers::FormColumnHelpers include ActiveScaffold::Helpers::SearchColumnHelpers include ActiveScaffold::Helpers::CountryHelpers include ActiveScaffold::Helpers::HumanConditionHelpers ## ## Delegates ## # access to the configuration variable def active_scaffold_config controller.class.active_scaffold_config end def active_scaffold_config_for(*args) controller.class.active_scaffold_config_for(*args) end def active_scaffold_controller_for(*args) controller.class.active_scaffold_controller_for(*args) end ## ## Uncategorized ## def controller_path_for_activerecord(klass) begin controller = active_scaffold_controller_for(klass) controller.controller_path rescue ActiveScaffold::ControllerNotFound controller = nil end end def generate_temporary_id (Time.now.to_f*1000).to_i.to_s end # Turns [[label, value]] into " : "" end end # Should this column be displayed in the subform? def in_subform?(column, parent_record) return true unless column.association # Polymorphic associations can't appear because they *might* be the reverse association, and because you generally don't assign an association from the polymorphic side ... I think. return false if column.polymorphic_association? # A column shouldn't be in the subform if it's the reverse association to the parent return false if column.association.reverse_for?(parent_record.class) return true end def form_remote_upload_tag(url_for_options = {}, options = {}) options[:target] = action_iframe_id(url_for_options) options[:multipart] ||= true options[:class] = "#{options[:class]} as_remote_upload".strip output="" output << form_tag(url_for_options, options) (output << "").html_safe end # Provides list of javascripts to include with +javascript_include_tag+ # You can use this with your javascripts like # <%= javascript_include_tag :defaults, 'your_own_cool_script', active_scaffold_javascripts, :cache => true %> def active_scaffold_javascripts(frontend = :default) ActiveScaffold::Config::Core.javascripts(frontend).collect do |name| ActiveScaffold::Config::Core.asset_path(name, frontend) end end # Provides stylesheets to include with +stylesheet_link_tag+ def active_scaffold_stylesheets(frontend = :default) [ActiveScaffold::Config::Core.asset_path("stylesheet.css", frontend)] end # Provides stylesheets for IE to include with +stylesheet_link_tag+ def active_scaffold_ie_stylesheets(frontend = :default) [ActiveScaffold::Config::Core.asset_path("stylesheet-ie.css", frontend)] end # easy way to include ActiveScaffold assets def active_scaffold_includes(*args) frontend = args.first.is_a?(Symbol) ? args.shift : :default options = args.first.is_a?(Hash) ? args.shift : {} js = javascript_include_tag(*active_scaffold_javascripts(frontend).push(options)) css = stylesheet_link_tag(*active_scaffold_stylesheets(frontend).push(options)) options[:cache] += '_ie' if options[:cache].is_a? String options[:concat] += '_ie' if options[:concat].is_a? String ie_css = stylesheet_link_tag(*active_scaffold_ie_stylesheets(frontend).push(options)) js + "\n" + css + "\n\n".html_safe end # a general-use loading indicator (the "stuff is happening, please wait" feedback) def loading_indicator_tag(options) image_tag "/images/active_scaffold/default/indicator.gif", :style => "visibility:hidden;", :id => loading_indicator_id(options), :alt => "loading indicator", :class => "loading-indicator" end # Creates a javascript-based link that toggles the visibility of some element on the page. # By default, it toggles the visibility of the sibling after the one it's nested in. You may pass custom javascript logic in options[:of] to change that, though. For example, you could say :of => '$("my_div_id")'. # You may also flag whether the other element is visible by default or not, and the initial text will adjust accordingly. def link_to_visibility_toggle(id, options = {}) options[:default_visible] = true if options[:default_visible].nil? options[:hide_label] = as_(:hide) options[:show_label] = as_(:show) javascript_tag("ActiveScaffold.create_visibility_toggle('#{id}', #{options.to_json});") end def skip_action_link(link, *args) (!link.ignore_method.nil? and controller.try(link.ignore_method, *args)) || ((link.security_method_set? or controller.respond_to? link.security_method) and !controller.send(link.security_method, *args)) end def render_action_link(link, url_options, record = nil, html_options = {}) url_options = action_link_url_options(link, url_options, record) html_options = action_link_html_options(link, url_options, record, html_options) action_link_html(link, url_options, html_options) end def render_group_action_link(link, url_options, options, record = nil) if link.type == :member && !options[:authorized] action_link_html(link, nil, {:class => "disabled #{link.action}#{link.html_options[:class].blank? ? '' : (' ' + link.html_options[:class])}"}) else render_action_link(link, url_options, record) end end def action_link_url_options(link, url_options, record, options = {}) url_options = url_options.clone url_options[:action] = link.action url_options[:controller] = link.controller if link.controller url_options.delete(:search) if link.controller and link.controller.to_s != params[:controller] url_options.merge! link.parameters if link.parameters @link_record = record url_options.merge! self.instance_eval(&(link.dynamic_parameters)) if link.dynamic_parameters.is_a?(Proc) @link_record = nil url_options_for_nested_link(link.column, record, link, url_options, options) if link.nested_link? url_options_for_sti_link(link.column, record, link, url_options, options) unless record.nil? || active_scaffold_config.sti_children.nil? url_options[:_method] = link.method if !link.confirm? && link.inline? && link.method != :get url_options end def action_link_html_options(link, url_options, record, html_options) link_id = get_action_link_id(url_options, record, link.column) html_options.reverse_merge! link.html_options.merge(:class => link.action) # Needs to be in html_options to as the adding _method to the url is no longer supported by Rails html_options[:method] = link.method if link.method != :get html_options['data-confirm'] = link.confirm(record.try(:to_label)) if link.confirm? html_options['data-position'] = link.position if link.position and link.inline? html_options[:class] += ' as_action' if link.inline? if link.popup? html_options['data-popup'] = true html_options[:target] = '_blank' end html_options[:id] = link_id html_options[:remote] = true unless link.page? || link.popup? if link.dhtml_confirm? html_options[:class] += ' as_action' if !link.inline? html_options[:page_link] = 'true' if !link.inline? html_options[:dhtml_confirm] = link.dhtml_confirm.value html_options[:onclick] = link.dhtml_confirm.onclick_function(controller, link_id) end html_options[:class] += " #{link.html_options[:class]}" unless link.html_options[:class].blank? html_options end def get_action_link_id(url_options, record = nil, column = nil) id = url_options[:id] || url_options[:parent_id] id = "#{column.association.name}-#{record.id}" if column && column.plural_association? if record.try(column.association.name.to_sym).present? id = "#{column.association.name}-#{record.send(column.association.name).id}" else id = "#{column.association.name}-#{record.id}" unless record.nil? end if column && column.singular_association? action_id = "#{id_from_controller(url_options[:controller]) + '-' if url_options[:parent_controller]}#{url_options[:action].to_s}" action_link_id(action_id, id) end def action_link_html(link, url, html_options) # issue 260, use url_options[:link] if it exists. This prevents DB data from being localized. label = url.delete(:link) if url.is_a?(Hash) label ||= link.label if link.image.nil? html = link_to(label, url, html_options) else html = link_to(image_tag(link.image[:name] , :size => link.image[:size], :alt => label), url, html_options) end # if url is nil we would like to generate an anchor without href attribute url.nil? ? html.sub(/href=".*?"/, '') : html end def url_options_for_nested_link(column, record, link, url_options, options = {}) if column && column.association url_options[:assoc_id] = url_options.delete(:id) url_options[:id] = record.send(column.association.name).id if column.singular_association? && record.send(column.association.name).present? link.eid = "#{controller_id.from(3)}_#{record.id}_#{column.association.name}" unless options.has_key?(:reuse_eid) url_options[:eid] = link.eid elsif link.parameters && link.parameters[:named_scope] url_options[:assoc_id] = url_options.delete(:id) link.eid = "#{controller_id.from(3)}_#{record.id}_#{link.parameters[:named_scope]}" unless options.has_key?(:reuse_eid) url_options[:eid] = link.eid end end def url_options_for_sti_link(column, record, link, url_options, options = {}) #need to find out controller of current record type #and set parameters sti_controller_path = controller_path_for_activerecord(record.class) if sti_controller_path url_options[:controller] = sti_controller_path url_options[:parent_sti] = controller_path end end def column_class(column, column_value, record) classes = [] classes << "#{column.name}-column" if column.css_class.is_a?(Proc) css_class = column.css_class.call(column_value, record) classes << css_class unless css_class.nil? else classes << column.css_class end unless column.css_class.nil? classes << 'empty' if column_empty? column_value classes << 'sorted' if active_scaffold_config.list.user.sorting.sorts_on?(column) classes << 'numeric' if column.column and [:decimal, :float, :integer].include?(column.column.type) classes.join(' ').rstrip end def column_heading_class(column, sorting) classes = [] classes << "#{column.name}-column_heading" classes << "sorted #{sorting.direction_of(column).downcase}" if sorting.sorts_on? column classes << column.css_class unless column.css_class.nil? || column.css_class.is_a?(Proc) classes.join(' ') end def column_empty?(column_value) empty = column_value.nil? empty ||= column_value.empty? if column_value.respond_to? :empty? empty ||= [' ', active_scaffold_config.list.empty_field_text].include? column_value if String === column_value return empty end def column_calculation(column) unless column.calculate.instance_of? Proc conditions = controller.send(:all_conditions) includes = active_scaffold_config.list.count_includes includes ||= controller.send(:active_scaffold_includes) unless conditions.nil? calculation = beginning_of_chain.calculate(column.calculate, column.name, :conditions => conditions, :joins => controller.send(:joins_for_collection), :include => includes) else column.calculate.call(@records) end end def render_column_calculation(column) calculation = column_calculation(column) override_formatter = "render_#{column.name}_#{column.calculate}" calculation = send(override_formatter, calculation) if respond_to? override_formatter "#{"#{as_(column.calculate)}: " unless column.calculate.is_a? Proc}#{format_column_value nil, column, calculation}" end def column_show_add_existing(column) (column.allow_add_existing and options_for_association_count(column.association) > 0) end def column_show_add_new(column, associated, record) value = column.plural_association? || (column.singular_association? and not associated.empty?) value = false unless record.class.authorized_for?(:crud_type => :create) value end def active_scaffold_error_messages_for(*params) options = params.extract_options!.symbolize_keys options.reverse_merge!(:container_tag => :div, :list_type => :ul) objects = Array.wrap(options.delete(:object) || params).map do |object| object = instance_variable_get("@#{object}") unless object.respond_to?(:to_model) object = convert_to_model(object) if object.class.respond_to?(:model_name) options[:object_name] ||= object.class.model_name.human.downcase end object end objects.compact! count = objects.inject(0) {|sum, object| sum + object.errors.count } unless count.zero? html = {} [:id, :class].each do |key| if options.include?(key) value = options[key] html[key] = value unless value.blank? else html[key] = 'errorExplanation' end end options[:object_name] ||= params.first header_message = if options.include?(:header_message) options[:header_message] else as_('errors.template.header', :count => count, :model => options[:object_name].to_s.gsub('_', ' ')) end message = options.include?(:message) ? options[:message] : as_('errors.template.body') error_messages = objects.sum do |object| object.errors.full_messages.map do |msg| options[:list_type] != :br ? content_tag(:li, msg) : msg end end error_messages = if options[:list_type] == :br error_messages.join('
').html_safe else content_tag(options[:list_type], error_messages.join.html_safe) end contents = [] contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank? contents << content_tag(:p, message) unless message.blank? contents << error_messages contents = contents.join.html_safe options[:container_tag] ? content_tag(options[:container_tag], contents, html) : contents else '' end end end end end