module Spider; module Components
class Switcher < Spider::Widget
tag 'switcher'
attr_to_scene :current
is_attribute :default
attr_reader :current, :current_label
default_template 'default'
def init
@sections = {}
@labels = {}
@links = {}
@first_link = nil
@content_by_label = {}
@labels_by_action = {}
@link_mode = :path
@current_action = nil
@inline_widgets = {}
@inline_w_order = []
end
def route_widget
return nil unless @current.is_a?(Spider::Widget)
[@current.id, @_action.split('/', 2)[1]]
end
def prepare(action='')
act = @_action_local || @default
@current_action = act
@scene.current_action = @current_action
if @labels_by_action[act] && content = @content_by_label[@labels_by_action[act]]
# must add the widget here so that it gets processed in super
add_widget(content) if content.is_a?(Spider::Widget)
end
init_widgets
# The widget object gets instantiated in super, so it is available now
@inline_w_order.each do |id|
iw = @inline_widgets[id]
add(iw[:label], @widgets[id], iw[:section])
end
redirect(widget_request_path+'/'+@first_link) if !act && @first_link
label = @labels_by_action[act]
content = @content_by_label[label]
raise NotFound.new(request_path) unless content
# content must not be set in inline, so it is not rendered by sp:run
@current = @inline_widgets[content.id.to_sym] ? nil : content
@current_label = label
super
@sections.each do |section, labels|
labels.each do |label|
menu_link = @link_mode == :path ? widget_request_path+'/'+@links[label] : "#{widget_request_path}?_wa[#{full_id}]=#{@links[label]}"
@widgets[:menu].add(label, menu_link, section)
end
end
@widgets[:menu].current = @current_label
end
def add(label, content, section=nil)
@sections[section] ||= []
@sections[section] << label
@labels[content] = label
@content_by_label[label] = content
w_act = self.class.label_to_link(label)
@first_link ||= w_act
@links[label] = w_act
@labels_by_action[w_act] = label
end
def widget_assets
res = @widgets[:menu].assets
res += @current.assets if @current
return res
end
def self.label_to_link(label)
label.downcase.gsub(/\s+/, '_').gsub(/[^a-zA-Z_]/, '')
end
def self.parse_content(doc)
ov = ""
@inline_widgets = []
doc.root.search('> [@id]').each do |w|
w_id = w.get_attribute('id')
w_label = w.get_attribute('switcher:label') || w_id
w_section = w.get_attribute('switcher:section')
w.remove_attribute('switcher:label')
w.remove_attribute('switcher:section')
ov += %Q{#{w.to_s}}
inline_attrs = %Q{id="#{w_id}" label="#{w_label}"}
inline_attrs += %Q{ section="#{w_section}"} if w_section
w.swap(%Q{})
end
override = Hpricot(%Q{#{ov}}).root
parse_override(override)
runtime, soverrides = super(doc)
return [runtime, [override] + soverrides]
end
def parse_runtime_content(doc, src_path)
doc = super
@inline_widgets = {}
doc.search('switcher:inline-widget').each do |w|
w_id = w.get_attribute('id').to_sym
@inline_widgets[w_id] = {:label => w.get_attribute('label')}
@inline_w_order << w_id
end
doc.search('switcher:inline-widget').remove
doc
end
end
end; end