module RailsConnector # @api public module CmsTagHelper FIELD_TYPES_WITH_ORIGINAL_CONTENT = %w[ enum html multienum reference referencelist string text ] VOID_TAGS = %w[area base br col command embed hr img input keygen link meta param source track wbr] # Returns an HTML block tag containing content from an Obj. # Add HTML attributes by passing an attributes hash to options. # The helper method is somewhat similar to (and internally uses) http://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag. # # This helper method also renders additional data attributes, which are needed for inplace editing. # These attributes are only rendered when appropriate, i.e. not for a regular visitor. # # @param tag_name [String, Symbol] Name of the html tag (e.g. +:h1+ or +:div+). # @param obj [Obj] A {Obj} from which attribute is read. # @param field_name [String, Symbol] Which field of the Obj should be rendered. # @param options [Hash] Additional options, which are passed to +content_tag+. Use them to add HTML attributes to the tag. # @param block [Proc] Optional block to render inner HTML. If none given the value of attribute will be rendered instead. # @return [String] The rendered html tag # # @example Renders an

tag containing the text of the +headline+ attribute of +@obj+ and assigns the tag a css class called +very_important+. # <%= cms_tag :h2, @obj, :headline, class: "very_important" %> # # @example Renders an

tag containing an escaped +headline+. # <%= cms_tag :h2, @obj, :headline do %> # <%= strip_tags @obj.headline %> # <% end %> # # @api public def cms_tag(tag_name, obj, field_name, options = {}, &block) begin field_type = obj.type_of_attribute(field_name.to_s) rescue RailsConnectorError => e return content_tag(tag_name, '', options) end options = options.merge({ 'data-ip-private-field-id' => obj.id, 'data-ip-field-obj-class' => obj.obj_class, 'data-ip-field-name' => field_name, 'data-ip-field-type' => field_type, }) if inplace_editing_allowed? if field_type == 'widget' rendered_widgets = obj.widgets(field_name).map do |widget| render_widget(widget, obj, field_name, obj) end inner_html = safe_join(rendered_widgets) else if inplace_editing_allowed? && FIELD_TYPES_WITH_ORIGINAL_CONTENT.include?(field_type) original_value = display_original_value(obj[field_name]) original_content = cms_tag_original_content(field_type, original_value) options['data-ip-private-field-original-content'] = MultiJson.encode(original_content) end inner_html = block_given? ? capture { yield } : display_value(obj[field_name]) end if VOID_TAGS.include?(tag_name.to_s) tag(tag_name, options) else content_tag(tag_name, inner_html, options) end end def cms_tag_original_content(field_type, field_value) case field_type when 'reference' then field_value.try(:id) when 'referencelist' then field_value.map(&:id) else field_value end end class List attr_reader :output def initialize(template) @template = template end # @param tag_name [String, Symbol] Name of the html tag (e.g. +:div+ or +:span+). # @param options [Hash] Additional options, which are passed to +content_tag+. Use them to add HTML attributes to the tag. # @return [String] The rendered html tag # # @example Render a
tag containing the text "random content" and assigns the tag a css class called +very_important+. # <%= list.tag :div, class: "very_important" do %> # random content # <% end %> def tag(tag_name, options = {}, &block) if @output.present? raise '"list.tag" can only be called once per iteration!' else @output = @template.content_tag(tag_name, options, &block) + "\n" nil end end end # @param tag_name [String, Symbol] Name of the html tag (e.g. +:h1+ or +:div+). # @param obj [Obj] A {Obj} from which method_name is read. # @param method_name [String, Symbol] Which method_name of the Obj should be rendered. Currently only +toclist+ is supported # @param options [Hash] Additional options, which are passed to +content_tag+. Use them to add HTML attributes to the tag. # @yieldparam [List] list An instance, where +tag+ should be called once. # @yieldparam [Obj] child Each child of +toclist+ # @return [String] The rendered html tag # # @example # <%= cms_tag_list :div, @obj, :toclist, class: "very_important" do |list, child| %> # <%= list.tag :div, class: "also_important" do %> # <%= link_to cms_path(child) do %> # <%= cms_tag :span, child, :title %> # <% end %> # <% end %> # <% end %> # # # results for an obj with two children in # # def cms_tag_list(tag_name, obj, method_name, options = {}) if method_name.to_s == 'toclist' items = obj.toclist else raise "#{method_name} is not (yet) supported. Currently only toclist is supported." end inner_html = "\n".html_safe items.each do |item| list = List.new(self) yield list, item inner_html << list.output end valid_page_classes = Obj.valid_page_classes_beneath(obj.path) options = options.merge({ 'data-ip-private-child-list-path' => obj.path, 'data-ip-private-child-list-allowed-classes' => valid_page_classes.to_json, }) if inplace_editing_allowed? content_tag(tag_name, inner_html, options) end def render_widget(widget, obj, field_name, container) renderer = WidgetRenderer.new(request) options = {} if inplace_editing_allowed? options['data-ip-private-widget-id'] = widget.id options['data-ip-private-widget-obj-class'] = widget.obj_class options['data-ip-private-widget-has-edit-view'] = true if renderer.has_edit_view?(widget.obj_class) end content_tag(:div, options) do renderer.process(:show, widget, obj, field_name, container) end end end end