Class: Spider::Widget

Inherits:
PageController show all
Includes:
HTTPMixin
Defined in:
lib/spiderfw/widget/widget.rb

Constant Summary collapse

@@common_attributes =
{
    :id => {}
}

Class Attribute Summary collapse

Instance Attribute Summary collapse

Attributes inherited from Controller

#dispatch_action, #executed_method, #is_target, #response

Attributes included from Dispatcher

#dispatch_previous

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from PageController

#get_route

Methods inherited from Controller

#action_target?, #after, app, before, before_methods, before_unless, #call_path, #check_action, controller_action?, controller_actions, default_action, #done, #done=, #done?, find_resource, find_resource_path, #get_action_method, #get_scene, #init, #is_target?, layout_path, option, options, #request_path, url, url=

Methods included from Annotations

included

Methods included from Logger

add, close, close_all, datetime_format, datetime_format=, #debug, debug, debug?, #debug?, enquire_loggers, #error, error, #error?, error?, #fatal, fatal, #fatal?, fatal?, info, #info, info?, #info?, method_missing, open, reopen, send_to_loggers, unknown, #unknown, #warn, warn, warn?, #warn?

Methods included from Dispatcher

#add_chain_item, #can_dispatch?, #dispatch, #dispatch_chain, #dispatch_next, #do_dispatch, #get_route, included, #route, #routes, #run_chain

Constructor Details

#initialize(request, response, scene = nil) ⇒ Widget

Returns a new instance of Widget.



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/spiderfw/widget/widget.rb', line 248

def initialize(request, response, scene=nil)
    super
    @is_target = false
    @widgets = {}
    @attributes = WidgetAttributes.new(self)
    @id_path = []
    @widget_attributes = {}
    locale = @request.locale.language
    # include_js = [
    #     '/js/jquery/jquery-1.4.2.js', '/js/inheritance.js', '/js/spider.js', '/js/jquery/plugins/jquery.query-2.1.6.js',
    #     '/js/jquery/plugins/jquery.form.js',
    #     '/js/plugins/plugin.js'
    # ]
    # # include_js << [
    # #     '/js/jquery/jquery-ui/development-bundle/ui/jquery-ui-1.7.2.custom.js',
    # #     #'/js/jquery/jquery-ui/development-bundle/ui/jquery-ui-1.7.2.custom.min.js',
    # #     "/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-#{locale}.js"
    # # ]
    # include_css = [
    #     '/css/spider.css', '/js/jquery/jquery-ui/css/smoothness/jquery-ui-1.7.2.custom.css', 
    # ]
    @assets = []
    # include_js.each{ |js| @assets << {:type => :js, :src => Spider::Components.pub_url+js, :path => Spider::Components.pub_path+js}}
    # include_css.each{ |css| @assets << {:type => :css, :src => Spider::Components.pub_url+css, :path => Spider::Components.pub_path+css}}
    # 
    @use_template ||= self.class.default_template
    @css_classes = []
    @widgets_runtime_content = {}
    @widget_procs = {}
    @runtime_overrides = []
    @_plugins = []
end

Class Attribute Details

.attributesObject (readonly)

Returns the value of attribute attributes.



23
24
25
# File 'lib/spiderfw/widget/widget.rb', line 23

def attributes
  @attributes
end

.scene_attributesObject (readonly)

Returns the value of attribute scene_attributes.



23
24
25
# File 'lib/spiderfw/widget/widget.rb', line 23

def scene_attributes
  @scene_attributes
end

Instance Attribute Details

#activeObject

Returns the value of attribute active.



16
17
18
# File 'lib/spiderfw/widget/widget.rb', line 16

def active
  @active
end

#attributesObject

Returns the value of attribute attributes.



15
16
17
# File 'lib/spiderfw/widget/widget.rb', line 15

def attributes
  @attributes
end

#containing_templateObject

Returns the value of attribute containing_template.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def containing_template
  @containing_template
end

#css_classesObject (readonly)

Returns the value of attribute css_classes.



15
16
17
# File 'lib/spiderfw/widget/widget.rb', line 15

def css_classes
  @css_classes
end

#idObject

Returns the value of attribute id.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def id
  @id
end

#id_pathObject

Returns the value of attribute id_path.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def id_path
  @id_path
end

#is_target_ancestorObject

Returns the value of attribute is_target_ancestor.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def is_target_ancestor
  @is_target_ancestor
end

#is_target_descendantObject

Returns the value of attribute is_target_descendant.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def is_target_descendant
  @is_target_descendant
end

#parentObject

Returns the value of attribute parent.



13
14
15
# File 'lib/spiderfw/widget/widget.rb', line 13

def parent
  @parent
end

#requestObject

Returns the value of attribute request.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def request
  @request
end

#sceneObject

Returns the value of attribute scene.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def scene
  @scene
end

#templateObject

Returns the value of attribute template.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def template
  @template
end

#widget_attributesObject (readonly)

Returns the value of attribute widget_attributes.



15
16
17
# File 'lib/spiderfw/widget/widget.rb', line 15

def widget_attributes
  @widget_attributes
end

#widgetsObject

Returns the value of attribute widgets.



14
15
16
# File 'lib/spiderfw/widget/widget.rb', line 14

def widgets
  @widgets
end

#widgets_runtime_contentObject (readonly)

Returns the value of attribute widgets_runtime_content.



15
16
17
# File 'lib/spiderfw/widget/widget.rb', line 15

def widgets_runtime_content
  @widgets_runtime_content
end

Class Method Details

.add_plugin(name, mod) ⇒ Object



200
201
202
203
204
# File 'lib/spiderfw/widget/widget.rb', line 200

def add_plugin(name, mod)
    @plugins ||= {}
    @plugins[name] = mod
    @subclasses.each{ |sub| sub.add_plugin(name, mod) } if @subclasses
end

.assetsObject



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/spiderfw/widget/widget.rb', line 216

def assets
    r = []
    if @default_assets
        @default_assets.each do |ass|
            if ass.is_a?(Hash)
                ass[:app] ||= self.class.app
                r << ass
            else
                r += Spider::Template.get_named_asset(ass)
            end
        end
    end
    if @plugins
        @plugins.each do |name, mod|
            r += mod.get_assets
        end
    end
    r
end

.attr_to_scene(*names) ⇒ Object



94
95
96
97
# File 'lib/spiderfw/widget/widget.rb', line 94

def attr_to_scene(*names)
    @scene_attributes ||= []
    names.each{ |name| @scene_attributes << name }
end

.attribute(name, params = {}) ⇒ Object



49
50
51
52
53
# File 'lib/spiderfw/widget/widget.rb', line 49

def attribute(name, params={})
    # TODO: implement, this is just a placeholder
    @attributes ||= @@common_attributes.clone
    @attributes[name] = params
end

.attribute?(name) ⇒ Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/spiderfw/widget/widget.rb', line 59

def attribute?(name)
    @attributes[name.to_sym]
end

.default_asset(ass) ⇒ Object



211
212
213
214
# File 'lib/spiderfw/widget/widget.rb', line 211

def default_asset(ass)
    @default_assets ||= []
    @default_assets << ass
end

.default_template(val = nil) ⇒ Object



124
125
126
127
128
# File 'lib/spiderfw/widget/widget.rb', line 124

def default_template(val=nil)
    @default_template = val if val
    @default_template ||= Spider::Inflector.underscore(self.name).split('/')[-1]
    @default_template
end

.get_scene_elementsObject



113
114
115
# File 'lib/spiderfw/widget/widget.rb', line 113

def get_scene_elements
    @scene_elements
end

.i_attr_accessor(name, params = {}) ⇒ Object



82
83
84
85
86
# File 'lib/spiderfw/widget/widget.rb', line 82

def i_attr_accessor(name, params={})
    params[:instance_attr] = true
    i_attribute(name, params)
    attr_accessor(name)
end

.i_attribute(name, params = {}) ⇒ Object



63
64
65
66
67
68
# File 'lib/spiderfw/widget/widget.rb', line 63

def i_attribute(name, params={})
    params[:instance_attr] = true
    params[:set_var] = true
    attribute(name, params)
    attr_reader(name)
end

.inherited(subclass) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/spiderfw/widget/widget.rb', line 26

def inherited(subclass)
    subclass.instance_variable_set(:@attributes, attributes.clone)
    subclass.instance_variable_set(:@scene_attributes, @scene_attributes.clone) if @scene_attributes
    subclass.instance_variable_set(:@plugins, @plugins.clone) if @plugins
    subclass.instance_variable_set(:@default_assets, @default_assets.clone) if @default_assets
    @subclasses ||= []
    @subclasses << subclass
    super
    # Do some magic to try and infer the widget's path, considering intermediate superclass callers
    cnt = 0
    s = subclass.superclass
    while s != Spider::Widget
        if caller[cnt].split(':')[-1] =~ /inherited/
            cnt += 1
        end
        s = s.superclass

    end
    file = caller[cnt].split(':')[0]
    subclass.instance_variable_set("@widget_path", File.dirname(file))
end

.is_attr_accessor(name, params = {}) ⇒ Object



88
89
90
91
92
# File 'lib/spiderfw/widget/widget.rb', line 88

def is_attr_accessor(name, params={})
    params[:instance_attr] = true
    is_attribute(name, params)
    attr_accessor(name)
end

.is_attribute(name, params = {}) ⇒ Object



70
71
72
73
74
75
# File 'lib/spiderfw/widget/widget.rb', line 70

def is_attribute(name, params={})
    params[:instance_attr] = true
    i_attribute(name, params)
    attr_to_scene(name)
    attr_reader(name)
end

.override_tagsObject

An array of custom tags that will be processed at compile time by the widget.



196
197
198
# File 'lib/spiderfw/widget/widget.rb', line 196

def override_tags
    return []
end

.parse_content(doc) ⇒ Object

Parses widget content at compile time. Must return a pair consisting of:

  • runtime content XML

  • an array of overrides (as Hpricot nodes)



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/spiderfw/widget/widget.rb', line 166

def parse_content(doc)
    overrides = []
    plugins = []
    to_del = []
    doc.root.each_child do |child|
        if child.respond_to?(:name)
            namespace, short_name = child.name.split(':', 2)
            if (namespace == 'tpl' && (Spider::Template.override_tags.include?(short_name) || self.override_tags.include?(child.name)))
                overrides << child unless child.is_a?(Hpricot::BogusETag)
            end
            if (child.name == 'sp:plugin')
                plugins << child
            end
        end
    end
    overrides.each do |ovr|
        parse_override(ovr)
    end

    Hpricot::Elements[*overrides].remove
    return [doc.to_s, overrides]
end

.parse_content_xml(xml) ⇒ Object



157
158
159
160
# File 'lib/spiderfw/widget/widget.rb', line 157

def parse_content_xml(xml)
    return ["", []] if !xml || xml.strip.empty?
    return parse_content(Hpricot(xml))
end

.parse_override(el) ⇒ Object

This method is called on each override node found. The widget must return the node, modifying it if needed.



191
192
193
# File 'lib/spiderfw/widget/widget.rb', line 191

def parse_override(el)
    return el
end

.plugin(name) ⇒ Object



206
207
208
209
# File 'lib/spiderfw/widget/widget.rb', line 206

def plugin(name)
    return nil unless @plugins
    @plugins[name]
end

.pub_pathObject



149
150
151
# File 'lib/spiderfw/widget/widget.rb', line 149

def pub_path
    self.app.pub_path
end

.pub_urlObject



138
139
140
141
142
143
144
145
146
147
# File 'lib/spiderfw/widget/widget.rb', line 138

def pub_url
    return self.app.pub_url
    w = self
    # FIXME! this is a quick hack to make extended templates work
    # but what we need is a better method to handle asset ownership
    #
    # Is it needed anymore?
    # w = w.superclass while w.superclass != Spider::Widget && w.superclass.subclass_of?(Spider::Widget)
    w.route_url+'/pub'
end

.register_tag(name) ⇒ Object



104
105
106
# File 'lib/spiderfw/widget/widget.rb', line 104

def register_tag(name)
    Spider::Template.register(name, self)
end

.relative_urlObject



130
131
132
# File 'lib/spiderfw/widget/widget.rb', line 130

def relative_url
    ::File.dirname(@widget_path)
end

.route_urlObject



134
135
136
# File 'lib/spiderfw/widget/widget.rb', line 134

def route_url
    Spider::ControllerMixins::HTTPMixin.reverse_proxy_mapping('/'+self.app.route_url+'/w/'+relative_url)
end

.runtime_content_tagsObject



153
154
155
# File 'lib/spiderfw/widget/widget.rb', line 153

def 
    ['sp:attribute']
end

.s_attribute(name, params = {}) ⇒ Object



77
78
79
80
# File 'lib/spiderfw/widget/widget.rb', line 77

def s_attribute(name, params={})
    attribute(name, params)
    attr_to_scene(name)
end

.scene_elements(*list) ⇒ Object



108
109
110
111
# File 'lib/spiderfw/widget/widget.rb', line 108

def scene_elements(*list)
    @scene_elements ||= []
    @scene_elements += list
end

.tag(name) ⇒ Object



99
100
101
102
# File 'lib/spiderfw/widget/widget.rb', line 99

def tag(name)
    self.app.register_tag(name, self)
    @tag_name ||= name
end

.template_pathObject



117
118
119
120
121
122
# File 'lib/spiderfw/widget/widget.rb', line 117

def template_path
    return @template_path if @template_path
    @template_path = @widget_path
    @template_path += '/templates' if @template_path && ::File.directory?(@template_path+'/templates')
    @template_path
end

Instance Method Details

#active?Boolean

Active widgets get prepared. When calling a deep widget, the ancestors will be active.

Returns:

  • (Boolean)


331
332
333
334
335
336
337
# File 'lib/spiderfw/widget/widget.rb', line 331

def active?
    return true if @active
    return true unless target_mode? || attributes[:"sp:target-only"]
    return true if @is_target || @is_target_ancestor
    return true if @is_target_descendant && !attributes[:"sp:target-only"]
    return false
end

#add_plugin(name) ⇒ Object



790
791
792
793
794
795
796
# File 'lib/spiderfw/widget/widget.rb', line 790

def add_plugin(name)
    mod = self.class.plugin(name)
    return unless mod
    self.extend(mod)
    @_plugins << mod
    @runtime_overrides << [name, mod.get_overrides, mod.overrides_path]
end

#add_widget(widget) ⇒ Object



569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
# File 'lib/spiderfw/widget/widget.rb', line 569

def add_widget(widget)
    widget.id_path = @id_path + [widget.id]
    widget.parent = self
    # widget.active = true if @is_target || @active
    @widgets[widget.id.to_sym] = widget
    if (@widgets_runtime_content[widget.id.to_sym])
        @widgets_runtime_content[widget.id.to_sym].each do |content|
            if (content[:widget])
                first, rest = content[:widget].split('/', 2)
                content[:widget] = rest
                widget.widgets_runtime_content[first.to_sym] ||= [] 
                widget.widgets_runtime_content[first.to_sym] << content
            else
                next if (content[:params] && !check_subwidget_conditions(widget, content[:params]))
                widget.parse_runtime_content_xml(content[:xml])
            end
        end
    end
    if (@widget_procs[widget.id.to_sym])
        @widget_procs[widget.id.to_sym].each do |wp|
            if (wp[:target])
                widget.with_widget(wp[:target], &wp[:proc])
            else
                widget.instance_eval(&wp[:proc])
            end
        end
    end
    widget
end

#assetsObject



709
710
711
712
# File 'lib/spiderfw/widget/widget.rb', line 709

def assets
    res = @assets.clone + widget_assets
    return res
end

#before(action = '') ⇒ Object



312
313
314
315
316
317
# File 'lib/spiderfw/widget/widget.rb', line 312

def before(action='')
    #Spider.logger.debug("Widget #{self} before(#{action})")
    widget_init(action)
    @before_done = true
    super
end

#before_done?Boolean

Returns:

  • (Boolean)


351
352
353
# File 'lib/spiderfw/widget/widget.rb', line 351

def before_done?
    @before_done
end

#check_subwidget_conditionsObject



599
600
601
# File 'lib/spiderfw/widget/widget.rb', line 599

def check_subwidget_conditions
    return false
end

#controller_action?(method) ⇒ Boolean

Returns:

  • (Boolean)


798
799
800
801
802
803
804
805
# File 'lib/spiderfw/widget/widget.rb', line 798

def controller_action?(method)
    r = super
    return r if r
    @_plugins.each do |pl|
        return r if r = pl.controller_action?(method)
    end
    return false
end

#create_widget(klass, id, *params) ⇒ Object



559
560
561
562
563
564
565
566
567
# File 'lib/spiderfw/widget/widget.rb', line 559

def create_widget(klass, id,  *params)
    klass = Spider::Template.get_registered_class(klass) unless klass.is_a?(Class)
    params.unshift(@response)
    params.unshift(@request)
    obj = klass.new(*params)
    obj.id = id
    add_widget(obj)
    return obj
end

#css_classObject



761
762
763
764
765
# File 'lib/spiderfw/widget/widget.rb', line 761

def css_class
    return @css_class if @css_class
    supers = self.class.ancestors.select{ |c| c != Spider::Widget && c.subclass_of?(Spider::Widget)}
    @css_class = Inflector.underscore(supers.join('/')).gsub('_', '-').gsub('/', ' ').split(' ').uniq.join(' ')
end

#css_model_class(model) ⇒ Object



767
768
769
# File 'lib/spiderfw/widget/widget.rb', line 767

def css_model_class(model)
    "model-#{model.name.gsub('::', '-')}"
end

#did_run?Boolean

Returns:

  • (Boolean)


483
484
485
# File 'lib/spiderfw/widget/widget.rb', line 483

def did_run?
    @did_run
end

#execute(action = '', *params) ⇒ Object



502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
# File 'lib/spiderfw/widget/widget.rb', line 502

def execute(action='', *params)
    Spider.logger.debug("Widget #{self} executing #{action}")
    widget_execute = @request.params['_we']
    if (@is_target)
        if (widget_execute)
            super(widget_execute, *params)
        else
            run
            render
        end
    elsif (@_widget)
        @_widget.set_action(widget_execute)
        @_widget.before(@_widget_rest, *params)
        @_widget.execute(@_widget_rest, *params)
    else
        super
    end
end

#find_widget(name) ⇒ Object



779
780
781
# File 'lib/spiderfw/widget/widget.rb', line 779

def find_widget(name)
    @widgets[name.to_sym] || super
end

#flashObject



550
551
552
553
# File 'lib/spiderfw/widget/widget.rb', line 550

def flash
    s = session(@request.session.flash, Spider::FlashHash)
    return s
end

#full_idObject



281
282
283
# File 'lib/spiderfw/widget/widget.rb', line 281

def full_id
    @id_path.join('-')
end

#has_params?Boolean

Returns:

  • (Boolean)


539
540
541
# File 'lib/spiderfw/widget/widget.rb', line 539

def has_params?
    !params.empty?
end

#indexObject



491
492
493
494
# File 'lib/spiderfw/widget/widget.rb', line 491

def index
    run
    render
end

#init_widget_done?Boolean

Returns:

  • (Boolean)


487
488
489
# File 'lib/spiderfw/widget/widget.rb', line 487

def init_widget_done?
    @init_widget_done
end

#init_widgets(template = @template) ⇒ Object



406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'lib/spiderfw/widget/widget.rb', line 406

def init_widgets(template=@template)
    load_widgets(template)
    @widgets.each do |id, w| 
        w.parent = self
        w.is_target_descendant = true if @is_target || @is_target_descendant
        w.active = true if run?
    end
    if !@is_target && @widget_target
        first, rest = @widget_target.split('/', 2)
        @_widget = find_widget(first)
        raise "#{self} couldn't find widget #{first} for target #{@widget_target}" unless @_widget
        @_widget.is_target_ancestor = true
        @_widget.widget_target = rest
        @_widget.is_target = true unless rest
        @_widget_rest = rest || ''
    end
    @init_widgets_done = true
    
end

#inspectObject



771
772
773
# File 'lib/spiderfw/widget/widget.rb', line 771

def inspect
    super + ", id: #{@id}"
end

#load_widgets(template = @template) ⇒ Object

Instantiates this widget’s own subwidgets.



427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/spiderfw/widget/widget.rb', line 427

def load_widgets(template=@template)
    if (self.class.scene_attributes)
        self.class.scene_attributes.each do |name|
            @scene[name] = instance_variable_get("@#{name}")
        end
    end
    template.request = @request
    template.response = @response
    template.runtime_overrides += @runtime_overrides
    template.init(@scene)
    template.widgets.each do |name, w|
        add_widget(w)
    end
end

#local_idObject



285
286
287
# File 'lib/spiderfw/widget/widget.rb', line 285

def local_id
    @id_path.last
end

#owner_controllerObject



723
724
725
726
727
728
729
730
# File 'lib/spiderfw/widget/widget.rb', line 723

def owner_controller
    w = self
    while (w.is_a?(Widget) && w.template && w.template.owner)
        return nil unless w.containing_template
        w = w.containing_template.owner
    end
    return w
end

#paramsObject



529
530
531
532
533
534
535
536
537
# File 'lib/spiderfw/widget/widget.rb', line 529

def params
    p = @request.params['_w']
    return {} unless p
    @id_path.each do |id| 
        p = p[id.to_s]
        return {} unless p
    end
    return p
end

#parse_runtime_content(doc, src_path = nil) ⇒ Object



630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
# File 'lib/spiderfw/widget/widget.rb', line 630

def parse_runtime_content(doc, src_path=nil)
    doc.search('sp:plugin').each do |plugin|
        # we don't call add_plugin here because the overrides don't have to be added at runtime, since
        # they have already been processed when compiling the instance
        name = plugin['name'].to_sym
        mod = self.class.plugin(name)
        next unless mod
        self.extend(mod)
    end
    # doc.search('sp:plugin').each do |plugin|
    #     name = plugin['name']
    #     mod = self.class.plugin(name)
    #     next unless mod
    #     (class <<self; self; end).instance_eval do
    #         debugger
    #         include mod
    #     end
    #     shadow = (class <<self; self; end)
    #     
    #     debugger
    #     a = 3
    # end
    doc.search('sp:runtime-content').each do |cont|
        w = cont.get_attribute('widget')
        first, rest = w.split('/', 2)
        params = nil
        if (first =~ /(.+)\[(.+)\]/)
            params = {}
            parts = $2.split(',')
            parts.each do |p|
                key, val = p.split('=')
                params[key] = val
            end
        end
        if (w)
            @widgets_runtime_content[first.to_sym] ||= []
            @widgets_runtime_content[first.to_sym] << {
                :widget => rest,
                :xml => "<sp:widget-content>#{cont.innerHTML}</sp:widget-content>",
                :params => params
            }
        end
    end
    doc.search('sp:runtime-content').remove
    
    attributes = doc.search('sp:attribute')
    attributes.each do |a|
        name = a.get_attribute('name').to_sym
        kvs = a.children ? a.children_of_type('sp:value') : []
        if (kvs.length > 0)
            value = {}
            kvs.each do |kv|
                key = kv.get_attribute('key')
                val = kv.innerText
                value[key] = val
            end
        else
            value = a.get_attribute('value')
        end
        if w = a.get_attribute('widget')
            @widget_attributes[w] ||= {}
            @widget_attributes[w][name] = value
        else
            @attributes[name] = value
        end
    end
    attributes.remove
    doc.search('sp:use-template').each do |templ|
        if templ.has_attribute?('app')
            owner = Spider.apps_by_path[templ.get_attribute('app')]
        else
            owner = self
        end
        @template = load_template(templ.get_attribute('src'), nil, owner)
    end
    return doc
end

#parse_runtime_content_xml(xml, src_path = nil) ⇒ Object



604
605
606
607
608
# File 'lib/spiderfw/widget/widget.rb', line 604

def parse_runtime_content_xml(xml, src_path=nil)
    return if xml.empty?
    doc = Hpricot(xml)
    parse_runtime_content(doc, src_path) if doc.children && doc.root && doc.root.children
end

#prepare(action = '') ⇒ Object

Recursively instantiates the subwidgets.



396
397
398
399
400
401
402
403
404
# File 'lib/spiderfw/widget/widget.rb', line 396

def prepare(action='')
    init_widgets unless @init_widgets_done
    set_widget_attributes
    prepare_widgets
    @template.assets.each do |res|
        res = res.clone
        @assets << res
    end
end

#prepare_scene(scene) ⇒ Object



732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
# File 'lib/spiderfw/widget/widget.rb', line 732

def prepare_scene(scene)
    scene = super
    
    # FIXME: owner_controller should be (almost) always defined
    scene.controller[:request_path] = owner_controller.request_path if owner_controller
    scene.widget[:request_path] = widget_request_path
    scene.widget[:target_only] = attributes[:"sp:target-only"]
    scene.widget[:is_target] = @is_target
    scene.widget[:is_running] = run?
    if (@parent && @parent.respond_to?(:scene) && @parent.scene)
        scene._parent = @parent.scene
    end
    par = @parent
    while par && par.is_a?(Widget)
        par = par.parent
    end
    scene.controller_scene = par.scene if par
    scene.extend(WidgetScene)
    return scene
end

#prepare_widgetsObject

Runs widget_before on all subwidgets.



461
462
463
464
465
466
467
468
469
470
# File 'lib/spiderfw/widget/widget.rb', line 461

def prepare_widgets
    r = route_widget
    @widgets.each do |id, w|
        if (r && r[0].to_sym == id)
            act = r[1]
        end
        act ||= ''
        w.widget_before(act)
    end
end

#renderObject



496
497
498
499
500
# File 'lib/spiderfw/widget/widget.rb', line 496

def render
    prepare_scene(@scene)
    set_scene_vars(@scene)
    @template.render(@scene) unless @is_target_ancestor && !@is_target
end

#replace_content_vars(str, scene = nil) ⇒ Object



610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
# File 'lib/spiderfw/widget/widget.rb', line 610

def replace_content_vars(str, scene=nil)
    scene ||= @parent && @parent.scene ? @parent.scene : @scene
    res = ""
    Spider::Template.scan_text(str) do |type, val, full|
        case type
        when :plain, :escaped_expr
            res << full
        when :expr
            Spider::Template.scan_scene_vars(val) do |vtype, vval|
                case vtype
                when :plain
                    res << vval
                when :var
                    res << scene[vval.to_sym].to_s
                end
            end
        end
    end
end

#route_widgetObject



296
297
298
# File 'lib/spiderfw/widget/widget.rb', line 296

def route_widget
    return nil
end

#run(action = '') ⇒ Object



473
474
475
476
477
478
479
480
481
# File 'lib/spiderfw/widget/widget.rb', line 473

def run(action='')
    @widgets.each do |wname, w|
        w.run if w.run?
    end
    if (@parent)
        @parent.after_widget(@id.to_sym)
    end
    @did_run = true
end

#run?Boolean

When in target mode, a widget will be run only if it is the target, or one of its subwidgets

Returns:

  • (Boolean)


340
341
342
343
344
345
# File 'lib/spiderfw/widget/widget.rb', line 340

def run?
    return true unless target_mode? || attributes[:"sp:target-only"]
    return true if @is_target # || @is_target_ancestor
    return true if @is_target_descendant && !attributes[:"sp:target-only"]
    return false
end

#session(container = @request.session, klass = Hash) ⇒ Object



543
544
545
546
547
548
# File 'lib/spiderfw/widget/widget.rb', line 543

def session(container=@request.session, klass=Hash)
    s = (container['_w'] ||= klass.new)
    @id_path[0..-2].each{ |id| s = (s[id] ||= klass.new) }
    s = (s[@id_path[-1]] ||= klass.new)
    return s
end

#set_scene_vars(scene) ⇒ Object



753
754
755
756
757
758
759
# File 'lib/spiderfw/widget/widget.rb', line 753

def set_scene_vars(scene)
    if (self.class.scene_attributes) # Repeat for new instance variables
        self.class.scene_attributes.each do |name|
            @scene[name] = instance_variable_get("@#{name}")
        end
    end
end

#set_widget_attributesObject



442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
# File 'lib/spiderfw/widget/widget.rb', line 442

def set_widget_attributes
    @widget_attributes.each do |w_id, a|
        w_id_parts = w_id.to_s.split('.', 2)
        if (w_id_parts[1])
            w_id = w_id_parts[0]
            sub_w = w_id_parts[1]
        end
        w_id = w_id.to_sym
        if (@widgets[w_id])
            if (sub_w)
                @widgets[w_id].widget_attributes[sub_w] = a
            else
                a.each{ |key, value| @widgets[w_id].attributes[key] = value}
            end
        end
    end
end

#to_sObject



775
776
777
# File 'lib/spiderfw/widget/widget.rb', line 775

def to_s
    super + ", id: #{@id}"
end

#transient_sessionObject



555
556
557
# File 'lib/spiderfw/widget/widget.rb', line 555

def transient_session
    return session(@request.session.transient, Spider::TransientHash)
end

#try_rescue(exc) ⇒ Object



521
522
523
524
525
526
527
# File 'lib/spiderfw/widget/widget.rb', line 521

def try_rescue(exc)
    if (exc.is_a?(NotFound))
        error("Widget path not found: #{exc.path}")
    else
        raise exc
    end
end

#widget_assetsObject



714
715
716
717
718
719
720
# File 'lib/spiderfw/widget/widget.rb', line 714

def widget_assets
    res = []
    @widgets.each do |id, w|
        res += w.assets
    end
    return res
end

#widget_before(action = '') ⇒ Object



319
320
321
322
323
324
325
326
327
# File 'lib/spiderfw/widget/widget.rb', line 319

def widget_before(action='')
    #Spider.logger.debug("Widget #{self} widget_before(#{action})")
    widget_init(action)
    return unless active?
    #Spider.logger.debug("Preparing widget #{self}")
    prepare_scene(@scene)
    prepare
    @before_done = true
end

#widget_init(action = '') ⇒ Object

Loads the template and sets the widget attributes



356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/spiderfw/widget/widget.rb', line 356

def widget_init(action='')
    action ||= ''
    if (@request.params['_wa'] && @request.params['_wa'][full_id])
        action = @request.params['_wa'][full_id]
    end
    @_action = action
    @_action_local, @_action_rest = action.split('/', 2)
    unless @template
        @template = load_template(@use_template)
    end
    prepare_template(@template)
    @id ||= @attributes[:id]
    @template.id_path = @id_path
    @template.mode = :widget
    required_groups = {}
    self.class.attributes.each do |k, params|
        if (params[:required])
            if (params[:required] == true && !@attributes[k])
                raise ArgumentError, "Attribute #{k} is required by widget #{self}"
            else
                if (!@attributes[k] && required_groups[params[:required]] != false)
                    required_groups[params[:required]] ||= []
                    required_groups[params[:required]] << k
                else
                    required_groups[params[:required]] = false
                end
            end 
        end
    end
    required_groups.each do |group_name, attributes|
        next if attributes == false
        raise ArgumentError, "Widget #{self} requires attribute #{attributes.join(' or ')} to be set"
    end
    if (@attributes[:class])
        @css_classes += @attributes[:class].split(/\s+/)
    end
end

#widget_request_pathObject



304
305
306
307
308
309
310
# File 'lib/spiderfw/widget/widget.rb', line 304

def widget_request_path
    p = @request.path
    i = p.index(@_action) if @_action && !@_action.empty?
    p = p[0..i-2] if i
    p = p.sub(/\/+$/, '')
    return p
end

#widget_target=(target) ⇒ Object



300
301
302
# File 'lib/spiderfw/widget/widget.rb', line 300

def widget_target=(target)
    @widget_target = target
end

#with_widget(path, &proc) ⇒ Object

FIXME: is the same in template. Refactor out.



784
785
786
787
788
# File 'lib/spiderfw/widget/widget.rb', line 784

def with_widget(path, &proc)
    first, rest = path.split('/', 2)
    @widget_procs[first.to_sym] ||= []
    @widget_procs[first.to_sym] << {:target => rest, :proc => proc }
end