Skip to content

Instantly share code, notes, and snippets.

@patrick99e99
Created December 10, 2008 10:01
Show Gist options
  • Save patrick99e99/34294 to your computer and use it in GitHub Desktop.
Save patrick99e99/34294 to your computer and use it in GitHub Desktop.
module WebpagesHelper
def display_html_content(contents, mode = nil)
completed_elements, dropzone_id_list, sortable_list, output = [], [], [], []
contents.map do |c|
unless completed_elements.include?(c.id)
result = get_nested_elements(c, contents, completed_elements, dropzone_id_list, sortable_list, mode)
# this makes result = [output, [element, dropzone]]
output << result[:output]
completed_elements = result[:completed_elements]
dropzone_id_list = result[:dropzone_id_list]
sortable_list = result[:sortable_list]
end
end
{:output => output.flatten, :dropzone_id_list => dropzone_id_list.uniq, :sortable_list => sortable_list.uniq}
end
def get_nested_elements(c, contents, completed_elements, dropzone_id_list, sortable_list, mode = nil)
# collect this element so it doesn't get duplicated
completed_elements << c.id
nested_items = contents.find_all_by_parent_id(c.id)
white_space = "\r\n"
output, nested, container_text = "", "", ""
the_id = "content_#{c.id}"
the_style = c.element.style
if mode == :sort && !nested_items.blank?
the_class = "sortable"
# the_style += "position: relative; z-index: 0; top: 0px; left: 0px;"
end
double_click = "new Ajax.Request('/webpages/edit_content', {asynchronous:true, evalScripts:true, parameters:'id=#{c.id}&webpage_id=#{c.webpage_id}&the_action=edit&authenticity_token=' + encodeURIComponent('#{form_authenticity_token}')}); return false;" if mode == :build && !c.data.blank?
# in sort mode, all things become 'divs' because scriptaculous can't seem to handle sorting multiple tags in one container
the_tag = mode == :sort ? :div : c.element.markup
output += content_tag the_tag, :id => the_id, :style => the_style, :class => the_class, :ondblclick => double_click do
# collect all elements nested so they don't get duplicated and get dropzone id's
if mode == :build && make_dropzone?(c)
# create a drop zone above element for building webpages
nested += surrounding_tags(output, c)
dropzone_id_list << "dropzone_#{c.id}"
end
container_text = c.element.name if mode == :sort && c.data.nil?
description = mode == :sort ? "<#{c.element.markup}> " : ""
nested += c.data.nil? ? container_text : "#{description}#{c.data}"
unless nested_items.blank?
sortable_list << the_id if nested_items.length > 1 && make_sortable?(c)
nested_items.map do |n|
# repeat process for all nested items
nested += white_space + get_nested_elements(n, contents, completed_elements, dropzone_id_list, sortable_list, mode)[:output]
end
end
white_space + nested + white_space
end
{:output => output, :completed_elements => completed_elements, :dropzone_id_list => dropzone_id_list, :sortable_list => sortable_list}
end
def surrounding_tags(output, c)
if c.element.markup == "ul"
the_tag = :li
else
the_tag = :div
end
output += content_tag the_tag, "Drag elements here for #{c.element.name}", :id => "dropzone_#{c.id}", :class => "drop_zone"
end
def make_dropzone?(c)
approved_list = ["div","ul"]
if approved_list.include?(c.element.markup)
true
else
false
end
end
def make_sortable?(c)
approved_list = ["ul", "div"]
if approved_list.include?(c.element.markup)
true
else
false
end
end
class ContentRenderer
def initialize(content, mode, template)
@mode = mode
@template = template
@content = content
end
def render_content
id = get_id
style = @content.element.style
title = get_title
double_click = get_double_click
image_source = get_image_source
content_tag get_html_tag, get_content_data, :src => image_source, :id => id, :style => style, :title => title, :ondblclick => double_click
end
def get_content_data
sortable = make_sortable
sortable_image + make_dropzone + parse_data + render_nested_contents.to_s + sortable
end
def render_nested_contents
@content.children.map do |c|
@content = c
render_content
end
end
def parse_data
unless @content.data.blank?
substitute @content.data, { :link => nil, :bold => :strong, :italic => :em }
else
if ( @mode == :display || containers.include?(@content.element.markup) || @content.photo_id )
""
else
get_container_name
end
end
end
def reg_exp
{ :link => /\[link(?:=(.*?))?\](.*?)\[\/link\]/,
:bold => /\[b\](.*?)\[\/b\]/,
:italic => /\[i\](.*?)\[\/i\]/ }
end
def substitute(content, options = {})
options.map { |k, v| k == :link ? link_substitute(content) : content.gsub!(reg_exp[k]) { content_tag v, $1 } }
content
end
def link_substitute(content)
if @mode == :display
content.gsub!(reg_exp[:link]) { $1.nil? ? link_to(nil, $2) : link_to($2, $1) }
else
content.gsub!(reg_exp[:link]) { content_tag :span, $2, :class => 'fake_link' }
end
end
def get_html_tag
@mode == :sort ? :div : @content.element.markup
end
def get_id
@mode == :display ? nil : "content_#{@content.id}"
end
def get_title
if @mode != :display && @content.parent
"inside #{@content.parent.element.name}"
end
end
def get_double_click(override = false)
remote_function(:url => content_path(@content.id), :method => :get) if @mode == :build && (!containers.include?(@content.element.markup) || override)
end
def get_image_source
formatted_photo_path(Photo.find(@content.photo_id), :png) unless @content.photo_id.nil?
end
def get_element
# scriptaculous requires all sortable elements in a container to be the same type
@mode == :sort ? :div : @content.element.markup
end
def get_container_name
"#{@content.element.name}" + (content_tag :span, "(id: #{@content.id})", :class => "builder_id_label")
end
def make_sortable
if @mode == :sort && @content.children.length > 1
sortable_element("content_#{@content.id}", :url => sort_contents_path(:id => @content.id), :tag => 'div')
else
""
end
end
def sortable_image
if @mode == :sort && @content.photo_id
image_tag formatted_thumb_photo_path(Photo.find(@content.photo_id), :png, :resize => "150x150")
else
""
end
end
def make_dropzone
if @mode == :build && containers.include?(@content.element.markup)
the_tag = @content.element.markup == "ul" ? :li : :div
(content_tag the_tag, "Drag elements here for #{get_container_name}", :id => "dropzone_#{@content.id}", :class => "drop_zone", :ondblclick => get_double_click(true)) +
drop_receiving_element("dropzone_#{@content.id}", :url => contents_path, :with => "'drop_id=#{@content.id}' + '&id=#{@content.webpage_id}' + '&drag_id=' + encodeURIComponent(element.id) + '&type=' + encodeURIComponent(element.tagName)" )
else
""
end
end
def containers
["ul","div"]
end
def method_missing(*args, &block)
@template.send(*args, &block)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment