Class: Wedge::Component

Inherits:
Object show all
Includes:
Methods
Defined in:
lib/wedge/component.rb

Direct Known Subclasses

Plugins::Form, Plugins::History, Plugins::Pjax

Constant Summary collapse

REJECTED_CLIENT_OPTS =
%i(scope file_path methods_wrapped events klass on on_server_methods added_class_events loaded html)

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Methods

#client?, included, #server?

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



313
314
315
316
317
318
319
# File 'lib/wedge/component.rb', line 313

def method_missing(method, *args, &block)
  if wedge_opts.scope.respond_to?(method, true)
    wedge_opts.scope.send method, *args, &block
  else
    super
  end
end

Class Method Details

.client_wedge_optsObject



170
171
172
# File 'lib/wedge/component.rb', line 170

def client_wedge_opts
  wedge_config.opts_dup.reject {|k, v| REJECTED_CLIENT_OPTS.include? k }
end

.configObject



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
# File 'lib/wedge/component.rb', line 151

def wedge_config
  @wedge_config ||= begin
    args = Wedge.config.opts_dup.merge(klass: self, object_events: {})

    unless RUBY_ENGINE == 'opal'
      args[:file_path] = caller.first.gsub(/(?<=\.rb):.*/, '')
      args[:path_name] = args[:file_path]
        .gsub(%r{(#{Dir.pwd}/|.*(?=wedge))}, '')
        .gsub(/\.rb$/, '')
    end

    c = Config.new(args)

    # If extending from a plugin it will automatically require it.
    ancestors.each do |klass|
      next if klass.to_s == name.to_s

      if klass.method_defined?(:wedge_opts) && klass.wedge_opts.name.to_s =~ /_plugin$/
        c.requires klass.wedge_opts.name
      end
    end

    c
  end
end

.domObject



108
109
110
# File 'lib/wedge/component.rb', line 108

def wedge_dom
  @wedge_dom ||= DOM.new wedge_opts.html
end

.method_missing(method, *args, &block) ⇒ Object



162
163
164
165
166
167
168
# File 'lib/wedge/component.rb', line 162

def method_missing(method, *args, &block)
  if wedge_opts.scope.respond_to?(method, true)
    wedge_opts.scope.send method, *args, &block
  else
    super
  end
end

.new(*args, &block) ⇒ Object

Override the default new behaviour



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
# File 'lib/wedge/component.rb', line 9

def new(*args, &block)
  obj = allocate

  obj.wedge_opts.js   = args.delete(:js)
  obj.wedge_opts.init = args.delete(:init)

  # Merge other args into opts
  args.each { |a| a.each {|k, v| obj.wedge_opts[k] = v } } if args.any?

  obj.wedge_opts.events.scope = obj

  # Set all the on events
  obj.wedge_opts.on.each do |*a, &b|
    obj.wedge_opts.events.add(*a.first.first, &a.first.last)
  end
  wedge_opts.added_class_events = true

  if obj.wedge_opts.init
    if obj.wedge_opts.init.is_a? Array
      obj.send :initialize, *obj.wedge_opts.init, &block
    else
      obj.send :initialize, obj.wedge_opts.init, &block
    end
  else
    obj.send :initialize, &block
  end

  unless wedge_opts.methods_wrapped
    obj.wedge_opts.methods_wrapped = wedge_opts.methods_wrapped = true

    public_instance_methods(false).each do |meth|
      alias_method :"wedge_original_#{meth}", :"#{meth}"
      define_method "#{meth}" do |*d_args, &blk|
        if server? && !wedge_opts.method_called && wedge_opts.js
          wedge_opts.method_called = meth
          wedge_opts.method_args   = *d_args
        end

        o_name = "wedge_original_#{meth}"

        if client? || method(o_name).parameters.length > 0
          result = send(o_name, *d_args, &blk)
        else
          result = send(o_name, &blk)
        end

        # Append the initialize javscript
        if server? && opts.js
          result = result.to_html if result.is_a? DOM
          result << wedge_javascript if result.is_a? String
        end

        result
      end
    end
  end

  obj
end

.optsOpenstruct, Config#opts

Shortcut for the Config#opts

Returns:



124
125
126
# File 'lib/wedge/component.rb', line 124

def wedge_opts
  wedge_config.opts
end

.tmplObject

Set templates

Examples:

tmpl :some_name, dom.find('#some-div')


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/wedge/component.rb', line 103

def wedge_tmpl(name, dom = false, remove = true)
  if dom
    dom = remove ? dom.remove : dom
    wedge_opts.tmpl[name] = {
      dom:  dom,
      html: dom.to_html
    }
  elsif t = wedge_opts.tmpl[name]
    dom = DOM.new t[:html]
  else
    false
  end

  dom
end

.wedge_componentsHash, Wedge.components Also known as: components

Shortcut for Wedge.components

Returns:



113
114
115
# File 'lib/wedge/component.rb', line 113

def wedge_components
  Wedge.components ||= {}
end

.wedge_configObject



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
# File 'lib/wedge/component.rb', line 126

def wedge_config
  @wedge_config ||= begin
    args = Wedge.config.opts_dup.merge(klass: self, object_events: {})

    unless RUBY_ENGINE == 'opal'
      args[:file_path] = caller.first.gsub(/(?<=\.rb):.*/, '')
      args[:path_name] = args[:file_path]
        .gsub(%r{(#{Dir.pwd}/|.*(?=wedge))}, '')
        .gsub(/\.rb$/, '')
    end

    c = Config.new(args)

    # If extending from a plugin it will automatically require it.
    ancestors.each do |klass|
      next if klass.to_s == name.to_s

      if klass.method_defined?(:wedge_opts) && klass.wedge_opts.name.to_s =~ /_plugin$/
        c.requires klass.wedge_opts.name
      end
    end

    c
  end
end

.wedge_domObject



105
106
107
# File 'lib/wedge/component.rb', line 105

def wedge_dom
  @wedge_dom ||= DOM.new wedge_opts.html
end

.wedge_on(*args, &block) ⇒ Object Also known as: on



153
154
155
156
157
158
159
# File 'lib/wedge/component.rb', line 153

def wedge_on(*args, &block)
  if args.first.to_s != 'server'
    wedge_opts.on << [args, block]
  else
    wedge_on_server(&block)
  end
end

.wedge_on_server(&block) ⇒ Object



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
# File 'lib/wedge/component.rb', line 174

def wedge_on_server(&block)
  if server?
    yield
  else
    m = Module.new(&block)

    m.public_instance_methods(false).each do |meth|
      wedge_opts.on_server_methods << meth.to_s

      define_method "#{meth}" do |*args, &blk|
        path_name = wedge_opts.path_name
        # event_id = "comp-event-#{$faye.generate_id}"

        payload = client_wedge_opts.reject do |k, _|
          %w(html tmpl requires plugins object_events js_loaded).include? k
        end
        payload[:method_called] = meth
        payload[:method_args]   = args

        HTTP.post("/#{wedge_opts.assets_url}/#{path_name}.call",
          headers: {
            'X-CSRF-TOKEN' => Element.find('meta[name=_csrf]').attr('content')
          },
          payload: payload) do |response|

            # We set the new csrf token
            xhr  = Native(response.xhr)
            csrf = xhr.getResponseHeader('BIO-CSRF-TOKEN')
            Element.find('meta[name=_csrf]').attr 'content', csrf
            ###########################

            res = JSON.from_object(`response`)

            blk.call res[:body], res
        end

        true
      end
    end

    include m
  end
end

.wedge_optsOpenstruct, Config#opts

Shortcut for the Config#opts

Returns:



121
122
123
# File 'lib/wedge/component.rb', line 121

def wedge_opts
  wedge_config.opts
end

.wedge_setup {|Config| ... } ⇒ Object Also known as: setup

Used to setup the component with default options.

Examples:

class SomeComponent < Component
  setup do |config|
    config.name :some
  end
end

Yields:



78
79
80
# File 'lib/wedge/component.rb', line 78

def wedge_setup(&block)
  block.call wedge_config
end

.wedge_tmpl(name, dom = false, remove = true) ⇒ Object

Set templates

Examples:

tmpl :some_name, dom.find('#some-div')


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/wedge/component.rb', line 88

def wedge_tmpl(name, dom = false, remove = true)
  if dom
    dom = remove ? dom.remove : dom
    wedge_opts.tmpl[name] = {
      dom:  dom,
      html: dom.to_html
    }
  elsif t = wedge_opts.tmpl[name]
    dom = DOM.new t[:html]
  else
    false
  end

  dom
end

Instance Method Details

#client_wedge_optsObject Also known as: client_opts



297
298
299
# File 'lib/wedge/component.rb', line 297

def client_wedge_opts
  wedge_config.opts_dup.reject {|k, v| REJECTED_CLIENT_OPTS.include? k }
end

#wedge(*args) ⇒ Object



308
309
310
# File 'lib/wedge/component.rb', line 308

def wedge(*args)
  Wedge[*args]
end

#wedge_configObject Also known as: config

Duplicate of class condig [Config]



221
222
223
224
225
226
227
228
# File 'lib/wedge/component.rb', line 221

def wedge_config
  @wedge_config ||= begin
    c = Config.new(self.class.wedge_config.opts_dup.merge(events: Events.new))
    c.opts.events.object_events = c.opts.object_events.dup
    c.opts.object_events = {}
    c
  end
end

#wedge_domObject Also known as: dom

Dom



247
248
249
250
251
252
253
254
255
# File 'lib/wedge/component.rb', line 247

def wedge_dom
  @wedge_dom ||= begin
    if server?
      DOM.new self.class.wedge_dom.to_html
    else
      DOM.new(Element)
    end
  end
end

#wedge_function(*args, &block) ⇒ Object Also known as: function

Special method that acts like the javascript equivalent

Examples:

foo = {
  bar: function { |moo|
    moo.call 'something'
  }
}.to_n


265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/wedge/component.rb', line 265

def wedge_function(*args, &block)
  args.any? && raise(ArgumentError, '`function` does not accept arguments')
  block || raise(ArgumentError, 'block required')
  proc do |*a|
    a.map! {|x| Native(`x`)}
    @this = Native(`this`)
    %x{
     var bs = block.$$s,
        result;
      block.$$s = null;
      result = block.apply(self, a);
      block.$$s = bs;
      
      return result;
    }
  end
end

#wedge_javascriptObject Also known as: javscript



284
285
286
287
288
289
290
291
292
293
294
# File 'lib/wedge/component.rb', line 284

def wedge_javascript
  return unless server?

  compiled_opts = Base64.encode64 client_wedge_opts.to_json
  name          = wedge_opts.file_path.gsub("#{Dir.pwd}/", '').gsub(/\.rb$/, '')

  javascript = <<-JS
    Wedge.javascript('#{name}', JSON.parse(Base64.decode64('#{compiled_opts}')))
  JS
  "<script>#{Opal.compile(javascript)}</script>"
end

#wedge_optsObject Also known as: opts

Duplicated of config.opts [Config#opts]



233
234
235
# File 'lib/wedge/component.rb', line 233

def wedge_opts
  wedge_config.opts
end

#wedge_tmpl(name) ⇒ Object Also known as: tmpl

Grab a copy of the template



240
241
242
# File 'lib/wedge/component.rb', line 240

def wedge_tmpl(name)
  self.class.wedge_tmpl name
end

#wedge_trigger(*args) ⇒ Object Also known as: trigger



302
303
304
# File 'lib/wedge/component.rb', line 302

def wedge_trigger(*args)
  wedge_opts.events.trigger(*args)
end