browserio 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,326 +0,0 @@
1
- module BrowserIO
2
- class Component
3
- include Methods
4
-
5
- REJECTED_CLIENT_OPTS = %i(scope file_path methods_wrapped events klass on on_server_methods added_class_events)
6
-
7
- class << self
8
- # Override the default new behaviour
9
- def new(*args, &block)
10
- obj = allocate
11
-
12
- obj.bio_opts.js = args.delete(:js)
13
- obj.bio_opts.init = args.delete(:init)
14
-
15
- # Merge other args into opts
16
- args.each { |a| a.each {|k, v| obj.bio_opts[k] = v } } if args.any?
17
-
18
- # Set all the requires
19
- unless RUBY_ENGINE == 'opal'
20
- obj.bio_opts.requires = obj.bio_config.get_requires
21
- end
22
-
23
- obj.bio_opts.events.scope = obj
24
-
25
- # Set all the on events
26
- obj.bio_opts.on.each do |*a, &b|
27
- obj.bio_opts.events.add(*a.first.first, &a.first.last)
28
- end
29
- bio_opts.added_class_events = true
30
-
31
- if obj.bio_opts.init
32
- if obj.bio_opts.init.is_a? Array
33
- obj.send :initialize, *obj.bio_opts.init, &block
34
- else
35
- obj.send :initialize, obj.bio_opts.init, &block
36
- end
37
- else
38
- obj.send :initialize, &block
39
- end
40
-
41
- unless bio_opts.methods_wrapped
42
- obj.bio_opts.methods_wrapped = bio_opts.methods_wrapped = true
43
-
44
- public_instance_methods(false).each do |meth|
45
- alias_method :"bio_original_#{meth}", :"#{meth}"
46
- define_method "#{meth}" do |*d_args, &blk|
47
- if bio_opts.js
48
- bio_opts.method_called = meth
49
- bio_opts.method_args = *d_args
50
- end
51
-
52
- o_name = "bio_original_#{meth}"
53
-
54
- if client? || method(o_name).parameters.length > 0
55
- result = send(o_name, *d_args, &blk)
56
- else
57
- result = send(o_name, &blk)
58
- end
59
-
60
- # Append the initialize javscript
61
- if server? && opts.js
62
- result = result.to_html if result.is_a? DOM
63
- result << bio_javascript
64
- end
65
-
66
- result
67
- end
68
- end
69
- end
70
-
71
- obj
72
- end
73
-
74
- # Used to setup the component with default options.
75
- #
76
- # @example
77
- # class SomeComponent < Component
78
- # setup do |config|
79
- # config.name :some
80
- # end
81
- # end
82
- # @yield [Config]
83
- def bio_setup(&block)
84
- block.call bio_config
85
- end
86
- alias_method :setup, :bio_setup
87
-
88
- # Set templates
89
- #
90
- # @example
91
- # tmpl :some_name, dom.find('#some-div')
92
- # @return dom [DOM]
93
- def bio_tmpl(name, dom = false, remove = true)
94
- if dom
95
- dom = remove ? dom.remove : dom
96
- bio_opts.tmpl[name] = {
97
- dom: dom,
98
- html: dom.to_html
99
- }
100
- elsif t = bio_opts.tmpl[name]
101
- dom = DOM.new t[:html]
102
- else
103
- false
104
- end
105
-
106
- dom
107
- end
108
- alias_method :tmpl, :bio_tmpl
109
-
110
- def bio_dom
111
- @bio_dom ||= DOM.new bio_opts.html
112
- end
113
- alias_method :dom, :bio_dom
114
-
115
- # Shortcut for BrowserIO.components
116
- #
117
- # @return [Hash, BrowserIO.components]
118
- def bio_components
119
- BrowserIO.components ||= {}
120
- end
121
- alias_method :components, :bio_components
122
-
123
- # Shortcut for the Config#opts
124
- #
125
- # @return [Openstruct, Config#opts]
126
- def bio_opts
127
- bio_config.opts
128
- end
129
- alias_method :opts, :bio_opts
130
-
131
- def bio_config
132
- @bio_config ||= begin
133
- args = BrowserIO.config.opts_dup.merge(klass: self, object_events: {})
134
-
135
- if server?
136
- args[:file_path] = caller.first.gsub(/(?<=\.rb):.*/, '')
137
- args[:path_name] = args[:file_path]
138
- .gsub(%r{(#{Dir.pwd}/|.*(?=browserio))}, '')
139
- .gsub(/\.rb$/, '')
140
- end
141
-
142
- c = Config.new(args)
143
-
144
- # If extending from a plugin it will automatically require it.
145
- ancestors.each do |klass|
146
- next if klass.to_s == name.to_s
147
-
148
- if klass.method_defined?(:bio_opts) && klass.bio_opts.name.to_s =~ /_plugin$/
149
- c.requires klass.bio_opts.name
150
- end
151
- end
152
-
153
- c
154
- end
155
- end
156
- alias_method :config, :bio_config
157
-
158
- def bio_on(*args, &block)
159
- if args.first.to_s != 'server'
160
- bio_opts.on << [args, block]
161
- else
162
- bio_on_server(&block)
163
- end
164
- end
165
- alias_method :on, :bio_on
166
-
167
- def method_missing(method, *args, &block)
168
- if bio_opts.scope.respond_to?(method, true)
169
- bio_opts.scope.send method, *args, &block
170
- else
171
- super
172
- end
173
- end
174
-
175
- def client_bio_opts
176
- bio_config.opts_dup.reject {|k, v| REJECTED_CLIENT_OPTS.include? k }
177
- end
178
-
179
- def bio_on_server(&block)
180
- if server?
181
- yield
182
- else
183
- m = Module.new(&block)
184
-
185
- m.public_instance_methods(false).each do |meth|
186
- bio_opts.on_server_methods << meth.to_s
187
-
188
- define_method "#{meth}" do |*args, &blk|
189
- path_name = bio_opts.path_name
190
- # event_id = "comp-event-#{$faye.generate_id}"
191
-
192
- payload = client_bio_opts.reject do |k, _|
193
- %w(html tmpl requires plugins object_events).include? k
194
- end
195
- payload[:method_called] = meth
196
- payload[:method_args] = args
197
-
198
- HTTP.post("/#{bio_opts.assets_url}/#{path_name}.call",
199
- headers: {
200
- 'X-CSRF-TOKEN' => Element.find('meta[name=_csrf]').attr('content')
201
- },
202
- payload: payload) do |response|
203
-
204
- # We set the new csrf token
205
- xhr = Native(response.xhr)
206
- csrf = xhr.getResponseHeader('BIO-CSRF-TOKEN')
207
- Element.find('meta[name=_csrf]').attr 'content', csrf
208
- ###########################
209
-
210
- res = JSON.from_object(`response`)
211
-
212
- blk.call res[:body], res
213
- end
214
-
215
- true
216
- end
217
- end
218
-
219
- include m
220
- end
221
- end
222
- end
223
-
224
- # Duplicate of class condig [Config]
225
- # @return config [Config]
226
- def bio_config
227
- @bio_config ||= begin
228
- c = Config.new(self.class.bio_config.opts_dup.merge(events: Events.new))
229
- c.opts.events.object_events = c.opts.object_events.dup
230
- c.opts.object_events = {}
231
- c
232
- end
233
- end
234
- alias_method :config, :bio_config
235
-
236
- # Duplicated of config.opts [Config#opts]
237
- # @return opts [Config#opts]
238
- def bio_opts
239
- bio_config.opts
240
- end
241
- alias_method :opts, :bio_opts
242
-
243
- # Grab a copy of the template
244
- # @return dom [DOM]
245
- def bio_tmpl(name)
246
- self.class.bio_tmpl name
247
- end
248
- alias_method :tmpl, :bio_tmpl
249
-
250
- # Dom
251
- # @return bio_dom [Dom]
252
- def bio_dom
253
- @bio_dom ||= begin
254
- if server?
255
- DOM.new self.class.bio_dom.to_html
256
- else
257
- DOM.new(Element)
258
- end
259
- end
260
- end
261
- alias_method :dom, :bio_dom
262
-
263
- # Special method that acts like the javascript equivalent
264
- # @example
265
- # foo = {
266
- # bar: function { |moo|
267
- # moo.call 'something'
268
- # }
269
- # }.to_n
270
- def bio_function(*args, &block)
271
- args.any? && raise(ArgumentError, '`function` does not accept arguments')
272
- block || raise(ArgumentError, 'block required')
273
- proc do |*a|
274
- a.map! {|x| Native(`x`)}
275
- @this = Native(`this`)
276
- %x{
277
- var bs = block.$$s,
278
- result;
279
- block.$$s = null;
280
- result = block.apply(self, a);
281
- block.$$s = bs;
282
-
283
- return result;
284
- }
285
- end
286
- end
287
- alias_method :function, :bio_function
288
-
289
- def bio_javascript
290
- return unless server?
291
-
292
- compiled_opts = Base64.encode64 client_bio_opts.to_json
293
- name = bio_opts.file_path.gsub("#{Dir.pwd}/", '').gsub(/\.rb$/, '')
294
-
295
- javascript = <<-JS
296
- BrowserIO.javascript('#{name}', JSON.parse(Base64.decode64('#{compiled_opts}')))
297
- JS
298
- "<script>#{Opal.compile(javascript)}</script>"
299
- end
300
- alias_method :javscript, :bio_javascript
301
-
302
- def client_bio_opts
303
- bio_config.opts_dup.reject {|k, v| REJECTED_CLIENT_OPTS.include? k }
304
- end
305
- alias_method :client_opts, :client_bio_opts
306
-
307
- def bio_trigger(*args)
308
- bio_opts.events.trigger(*args)
309
- end
310
- alias_method :trigger, :bio_trigger
311
-
312
- if RUBY_ENGINE == 'opal'
313
- def bio(*args)
314
- BrowserIO[*args]
315
- end
316
- end
317
-
318
- def method_missing(method, *args, &block)
319
- if bio_opts.scope.respond_to?(method, true)
320
- bio_opts.scope.send method, *args, &block
321
- else
322
- super
323
- end
324
- end
325
- end
326
- end
@@ -1,120 +0,0 @@
1
- require 'ostruct'
2
- require 'browserio/events'
3
-
4
- module BrowserIO
5
- class Config
6
- include Methods
7
-
8
- # Stores the options for the config
9
- #
10
- # @return [OpenStruct]
11
- attr_accessor :opts
12
-
13
- # Setup initial opts values
14
- #
15
- # @param opts [Hash] The initial params for #opts.
16
- def initialize(opts = {})
17
- opts = {
18
- tmpl: IndifferentHash.new,
19
- scope: false,
20
- loaded: false,
21
- requires: [],
22
- on: [],
23
- on_server_methods: [],
24
- object_events: {},
25
- is_plugin: false,
26
- plugins: []
27
- }.merge opts
28
-
29
- @opts = OpenStruct.new(opts)
30
- end
31
-
32
- # Set the unique name of the component
33
- #
34
- # @param name [<String, Symbol>, #to_sym]
35
- def name(name)
36
- opts.name = name.to_sym
37
- opts.is_plugin = true if name.to_s =~ /_plugin$/
38
- BrowserIO.components ||= {}
39
- BrowserIO.components[opts.name] = opts
40
- end
41
-
42
- def is_plugin?
43
- opts.is_plugin
44
- end
45
-
46
- %w(scope assets_url).each do |m|
47
- define_method m do |v|
48
- opts[m] = v
49
- end
50
- end
51
-
52
- # Used to set and update the dom
53
- def dom
54
- if server?
55
- yield
56
- end
57
- end
58
-
59
- # Set the raw html
60
- # @param html [String]
61
- def html(html)
62
- unless RUBY_ENGINE == 'opal'
63
- opts.html = begin
64
- File.read html
65
- rescue
66
- html
67
- end.strip
68
- end
69
- end
70
-
71
- def requires(*args)
72
- unless RUBY_ENGINE == 'opal'
73
- args.each do |a|
74
- if a.to_s[/_plugin$/]
75
- require "browserio/plugins/#{a.to_s.gsub(/_plugin$/, '')}"
76
- end
77
- opts.requires << a
78
- end
79
- end
80
- end
81
-
82
- def opts_dup
83
- opts.to_h.inject({}) {|copy, (key, value)| copy[key] = value.dup rescue value; copy}
84
- end
85
-
86
- def plugin(name)
87
- unless RUBY_ENGINE == 'opal'
88
- require "browserio/plugins/#{name}"
89
- end
90
- end
91
-
92
- def get_requires(requires = false, previous_requires = [])
93
- list = []
94
-
95
- unless requires
96
- requires ||= opts.requires.dup
97
- previous_requires << opts.name.to_sym
98
- end
99
-
100
- previous_requires.each { |p| requires.delete(p) }
101
-
102
- requires.each do |r|
103
- klass = BrowserIO.components[r.to_sym].klass
104
- o = klass.client_bio_opts.select do |k, v|
105
- %w(path_name name assets_url requires).include? k.to_s
106
- end
107
-
108
- # We don't want to get a stack limit error so we stop something
109
- # requiring itself
110
- pr = previous_requires.dup << o[:name].to_sym
111
-
112
- o[:requires] = get_requires o[:requires].dup, pr if o[:requires].present?
113
-
114
- list << o
115
- end
116
-
117
- list
118
- end
119
- end
120
- end
@@ -1,139 +0,0 @@
1
- module BrowserIO
2
- class DOM
3
- include Methods
4
-
5
- attr_accessor :dom, :raw_html
6
-
7
- class << self
8
- # Shortcut for creating dom
9
- # @param html [String]
10
- # @return dom [DOM]
11
- def [] html
12
- new html
13
- end
14
- end
15
-
16
- def initialize html
17
- @raw_html = html
18
-
19
- if server?
20
- @dom = raw_html.is_a?(String) ? HTML[raw_html.dup] : raw_html
21
- else
22
- @dom = raw_html.is_a?(String) ? Element[raw_html.dup] : raw_html
23
- end
24
- end
25
-
26
- def find string, &block
27
- if client?
28
- node = DOM.new dom.find(string)
29
- elsif server?
30
- if block_given?
31
- node = DOM.new dom.css(string)
32
- else
33
- node = DOM.new dom.at(string)
34
- end
35
- end
36
-
37
- if block_given?
38
- node.each_with_index do |n, i|
39
- block.call DOM.new(n), i
40
- end
41
- end
42
-
43
- node
44
- end
45
-
46
- if RUBY_ENGINE == 'ruby'
47
- def data key = false, value = false
48
- d = Hash[node.xpath("@*[starts-with(name(), 'data-')]").map{|a| [a.name, a.value]}]
49
-
50
- if !key
51
- d
52
- elsif key && !value
53
- d[key]
54
- else
55
- node["data-#{key}"] = value
56
- end
57
- end
58
-
59
- def val value
60
- node.content = value
61
- end
62
-
63
- def add_class classes
64
- classes = (classes || '').split ' ' unless classes.is_a? Array
65
- new_classes = ((node.attr('class') || '').split(' ') << classes).uniq.join(' ')
66
- node['class'] = new_classes
67
- end
68
-
69
- def remove_class classes
70
- classes = (classes || '').split ' ' unless classes.is_a? Array
71
- (node.attr('class') || '').split(' ').reject { |n| n =~ /active|asc|desc/i }.join(' ')
72
- end
73
-
74
- def attr key, value = false
75
- if value
76
- value = value.join ' ' if value.is_a? Array
77
- node[key] = value
78
- else
79
- super key
80
- end
81
- end
82
- end
83
-
84
- def html= content
85
- if server?
86
- node.inner_html = content
87
- else
88
- content = content.dom if content.is_a? BrowserIO::DOM
89
- node.html content
90
- end
91
-
92
- node
93
- end
94
-
95
- if RUBY_ENGINE == 'opal'
96
- # make it supply the jquery element so it will use that as it doesn't
97
- # know how to handle the DOM element.
98
- %w(append prepend replace_with after before).each do |meth|
99
- define_method meth do |obj|
100
- obj = obj.dom if obj.is_a? BrowserIO::DOM
101
- super obj
102
- end
103
- end
104
-
105
- def to_html
106
- @dom ||= DOM.new '<div>'
107
- el = dom.first
108
- DOM.new('<div>').append(el).html
109
- end
110
- end
111
-
112
- def html content = false
113
- if !content
114
- if server?
115
- node.inner_html
116
- else
117
- node ? node.html : dom.html
118
- end
119
- else
120
- self.html = content
121
- end
122
- end
123
-
124
- def node
125
- @node || dom
126
- end
127
-
128
- # This allows you to use all the nokogiri or opal jquery methods if a
129
- # global one isn't set
130
- def method_missing method, *args, &block
131
- # respond_to?(symbol, include_all=false)
132
- if dom.respond_to? method, true
133
- dom.send method, *args, &block
134
- else
135
- super
136
- end
137
- end
138
- end
139
- end