boxes_helper.rb
8.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
module BoxesHelper
  def insert_boxes(content)
    if controller.send(:boxes_editor?) && controller.send(:uses_design_blocks?)
      content + display_boxes_editor(controller.boxes_holder)
    else
      maybe_display_custom_element(controller.boxes_holder, :custom_header_expanded, :id => 'profile-header') +
      if controller.send(:uses_design_blocks?)
        display_boxes(controller.boxes_holder, content)
      else
        content_tag('div',
          content_tag('div',
            content_tag('div', wrap_main_content(content), :class => 'no-boxes-inner-2'),
            :class => 'no-boxes-inner-1'
          ),
          :class => 'no-boxes'
        )
      end +
      maybe_display_custom_element(controller.boxes_holder, :custom_footer_expanded, :id => 'profile-footer')
    end
  end
  def box_decorator
    @box_decorator || DontMoveBlocks
  end
  def with_box_decorator(dec, &block)
    @box_decorator = dec
    result = block.call
    @box_decorator = DontMoveBlocks
    result
  end
  def display_boxes_editor(holder)
    with_box_decorator self do
      content_tag('div', display_boxes(holder, '<' + _('Main content') + '>'), :id => 'box-organizer')
    end
  end
  def display_boxes(holder, main_content)
    boxes = holder.boxes.first(holder.boxes_limit)
    content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n")
    content = main_content if (content.blank?)
    content_tag('div', content, :class => 'boxes', :id => 'boxes' )
  end
  def maybe_display_custom_element(holder, element, options = {})
    if holder.respond_to?(element)
      content_tag('div', holder.send(element), options)
    else
      ''
    end
  end
  def display_box(box, main_content)
    content_tag('div', content_tag('div', display_box_content(box, main_content), :class => 'blocks'), :class => "box box-#{box.position}", :id => "box-#{box.id}" )
  end
  def display_updated_box(box)
    with_box_decorator self do
      display_box_content(box, '<' + _('Main content') + '>')
    end
  end
  def display_box_content(box, main_content)
    context = { :article => @page, :request_path => request.path, :locale => locale }
    box_decorator.select_blocks(box.blocks.includes(:box), context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box)
  end
  def select_blocks(arr, context)
    arr
  end
  def display_block(block, main_content = nil)
    render :file => 'shared/block', :locals => {:block => block, :main_content => main_content, :use_cache => use_cache? }
  end
  def use_cache?
    box_decorator == DontMoveBlocks
  end
  def display_block_content(block, person, main_content = nil)
    content = block.main? ? wrap_main_content(main_content) : block.content({:person => person})
    result = extract_block_content(content)
    footer_content = extract_block_content(block.footer)
    unless footer_content.blank?
      footer_content = content_tag('div', footer_content, :class => 'block-footer-content' )
    end
    options = {
      :class => classes = ['block', block_css_classes(block) ].uniq.join(' '),
      :id => "block-#{block.id}"
    }
    if ( block.respond_to? 'help' )
      options[:help] = block.help
    end
    unless block.visible?
      options[:title] = _("This block is invisible. Your visitors will not see it.")
    end
    controller.send(:content_editor?) || @plugins.each do |plugin|
      result = plugin.parse_content(result)
    end
    box_decorator.block_target(block.box, block) +
      content_tag('div',
       content_tag('div',
         content_tag('div',
           result + footer_content + box_decorator.block_edit_buttons(block),
           :class => 'block-inner-2'),
         :class => 'block-inner-1'),
       options) +
    box_decorator.block_handle(block)
  end
  def wrap_main_content(content)
    (1..8).to_a.reverse.inject(content) { |acc,n| content_tag('div', acc, :id => 'main-content-wrapper-' + n.to_s) }
  end
  def extract_block_content(content)
    case content
    when Hash
      content_tag('iframe', '', :src => url_for(content))
    when String
      if content.split("\n").size == 1 and content =~ /^https?:\/\//
        content_tag('iframe', '', :src => content)
      else
        content
      end
    when Proc
      self.instance_eval(&content)
    when NilClass
      ''
    else
      raise "Unsupported content for block (#{content.class})"
    end
  end
  module DontMoveBlocks
    # does nothing
    def self.block_target(box, block = nil)
      ''
    end
    # does nothing
    def self.block_handle(block)
      ''
    end
    def self.block_edit_buttons(block)
      ''
    end
    def self.select_blocks(arr, context)
      arr.select { |block| block.visible?(context) }
    end
  end
  # generates a place where you can drop a block and get the block moved to
  # there.
  #
  # If +block+ is not nil, then it means "place the dropped block before this
  # one.". Otherwise, it means "place the dropped block at the end of the
  # list"
  #
  # +box+ is always needed
  def block_target(box, block = nil)
    id =
      if block.nil?
        "end-of-box-#{box.id}"
      else
        "before-block-#{block.id}"
      end
    content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
  end
  # makes the given block draggable so it can be moved away.
  def block_handle(block)
    draggable_element("block-#{block.id}", :revert => true)
  end
  def block_edit_buttons(block)
    buttons = []
    nowhere = 'javascript: return false;'
    if block.first?
      buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
    else
      buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })
    end
    if block.last?
      buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)
    else
      buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})
    end
    holder = block.owner
    # move to opposite side
    # FIXME too much hardcoded stuff
    if holder.layout_template == 'default'
      if block.box.position == 2 # area 2, left side => move to right side
        buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )
      elsif block.box.position == 3 # area 3, right side => move to left side
        buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
      end
    end
    if block.editable?
      buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
    end
    if !block.main?
      buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
    end
    if block.respond_to?(:help)
      buttons << thickbox_inline_popup_icon(:help, _('Help on this block'), {}, "help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + thickbox_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}")
    end
    content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar')
  end
  def current_blocks
    controller.boxes_holder.boxes.map(&:blocks).inject([]){|ac, a| ac + a}
  end
  # DEPRECATED. Do not use this.
  def import_blocks_stylesheets(options = {})
    @blocks_css_files ||= current_blocks.map{|b|'blocks/' + block_css_class_name(b)}.uniq
    stylesheet_import(@blocks_css_files, options)
  end
  def block_css_class_name(block)
    block.class.name.underscore.gsub('_', '-')
  end
  def block_css_classes(block)
    classes = block_css_class_name(block)
    classes += ' invisible-block' if block.display == 'never'
    classes
  end
end