Module: Glimmer::Web::Component
- Includes:
- DataBinding::ObservableModel
- Included in:
- AddressForm, AddressPage, ButtonCounter, ContactForm, ContactTable, HelloFormMvp, HelloObserver, HelloParagraph, NewTodoForm, TodoFilters, TodoInput, TodoList, TodoListItem, TodoMvc, TodoMvcFooter
- Defined in:
- lib/glimmer/web/component.rb
Defined Under Namespace
Modules: ClassMethods, GlimmerSupersedable
Constant Summary
collapse
- ADD_COMPONENT_KEYWORDS_UPON_INHERITANCE =
proc do
class << self
def inherited(subclass)
Glimmer::Web::Component.add_component_keyword_to_classes_map_for(subclass)
subclass.class_eval(&Glimmer::Web::Component::ADD_COMPONENT_KEYWORDS_UPON_INHERITANCE)
end
end
end
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#add_observer(observer, attribute_name) ⇒ Object
-
#attribute_setter(attribute_name) ⇒ Object
-
#bind_content(*binding_args, &content_block) ⇒ Object
-
#can_add_observer?(attribute_name) ⇒ Boolean
-
#can_handle_observation_request?(observation_request) ⇒ Boolean
-
#content(*args, &block) ⇒ Object
Returns content block if used as an attribute reader (no args) Otherwise, if a block is passed, it adds it as content to this Glimmer web component.
-
#data_bind(property, model_binding) ⇒ Object
-
#get_attribute(attribute_name) ⇒ Object
-
#handle_observation_request(observation_request, block) ⇒ Object
-
#has_attribute?(attribute_name, *args) ⇒ Boolean
-
#has_instance_method?(method_name) ⇒ Boolean
This method ensures it has an instance method not coming from Glimmer DSL.
-
#initialize(parent, args, options, &content) ⇒ Object
-
#local_respond_to? ⇒ Object
-
#method_missing(method_name, *args, &block) ⇒ Object
-
#observer_registrations ⇒ Object
This stores observe keyword registrations of model/attribute observers.
-
#post_add_content ⇒ Object
-
#post_initialize_child(child) ⇒ Object
Subclasses may override to perform post initialization work on an added child.
-
#remove ⇒ Object
-
#render(parent: nil, custom_parent_dom_element: nil, brand_new: false) ⇒ Object
-
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
-
#set_attribute(attribute_name, *args) ⇒ Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
329
330
331
332
333
334
335
336
337
|
# File 'lib/glimmer/web/component.rb', line 329
def method_missing(method_name, *args, &block)
if can_handle_observation_request?(method_name)
handle_observation_request(method_name, block)
elsif markup_root.respond_to?(method_name, true)
markup_root.send(method_name, *args, &block)
else
super(method_name, *args, &block)
end
end
|
Instance Attribute Details
#args ⇒ Object
Returns the value of attribute args.
179
180
181
|
# File 'lib/glimmer/web/component.rb', line 179
def args
@args
end
|
#markup_root ⇒ Object
Returns the value of attribute markup_root.
179
180
181
|
# File 'lib/glimmer/web/component.rb', line 179
def markup_root
@markup_root
end
|
#options ⇒ Object
Returns the value of attribute options.
179
180
181
|
# File 'lib/glimmer/web/component.rb', line 179
def options
@options
end
|
#parent ⇒ Object
Also known as:
parent_proxy
Returns the value of attribute parent.
179
180
181
|
# File 'lib/glimmer/web/component.rb', line 179
def parent
@parent
end
|
Class Method Details
.add_component_keyword_to_classes_map_for(component_class) ⇒ Object
.component_keyword_to_classes_map ⇒ Object
164
165
166
|
# File 'lib/glimmer/web/component.rb', line 164
def component_keyword_to_classes_map
@component_keyword_to_classes_map ||= reset_component_keyword_to_classes_map
end
|
.for(underscored_component_name) ⇒ Object
142
143
144
145
146
147
148
149
150
|
# File 'lib/glimmer/web/component.rb', line 142
def for(underscored_component_name)
component_classes = Glimmer::Web::Component.component_keyword_to_classes_map[underscored_component_name]
if component_classes.nil? || component_classes.empty?
Glimmer::Config.logger.debug {"#{underscored_component_name} has no Glimmer web component class!" }
nil
else
component_class = component_classes.first
end
end
|
.included(klass) ⇒ Object
.interpretation_stack ⇒ Object
172
173
174
|
# File 'lib/glimmer/web/component.rb', line 172
def interpretation_stack
@interpretation_stack ||= []
end
|
.keywords_for_class(component_class) ⇒ Object
159
160
161
162
|
# File 'lib/glimmer/web/component.rb', line 159
def keywords_for_class(component_class)
namespaces = component_class.to_s.split(/::/).map(&:underscore).reverse
namespaces.size.times.map { |n| namespaces[0..n].reverse.join('__') }
end
|
.reset_component_keyword_to_classes_map ⇒ Object
168
169
170
|
# File 'lib/glimmer/web/component.rb', line 168
def reset_component_keyword_to_classes_map
@component_keyword_to_classes_map = {}
end
|
Instance Method Details
#add_observer(observer, attribute_name) ⇒ Object
256
257
258
259
260
261
262
|
# File 'lib/glimmer/web/component.rb', line 256
def add_observer(observer, attribute_name)
if has_instance_method?(attribute_name)
super(observer, attribute_name)
else
@markup_root.add_observer(observer, attribute_name)
end
end
|
#attribute_setter(attribute_name) ⇒ Object
293
294
295
|
# File 'lib/glimmer/web/component.rb', line 293
def attribute_setter(attribute_name)
"#{attribute_name}="
end
|
#bind_content(*binding_args, &content_block) ⇒ Object
310
311
312
|
# File 'lib/glimmer/web/component.rb', line 310
def bind_content(*binding_args, &content_block)
@markup_root&.bind_content(*binding_args, &content_block)
end
|
#can_add_observer?(attribute_name) ⇒ Boolean
252
253
254
|
# File 'lib/glimmer/web/component.rb', line 252
def can_add_observer?(attribute_name)
has_instance_method?(attribute_name) || has_instance_method?("#{attribute_name}?") || @markup_root.can_add_observer?(attribute_name)
end
|
#can_handle_observation_request?(observation_request) ⇒ Boolean
232
233
234
235
236
237
238
239
240
|
# File 'lib/glimmer/web/component.rb', line 232
def can_handle_observation_request?(observation_request)
observation_request = observation_request.to_s
result = false
if observation_request.start_with?('on_updated_')
property = observation_request.sub(/^on_updated_/, '')
result = can_add_observer?(property)
end
result || markup_root&.can_handle_observation_request?(observation_request)
end
|
#content(*args, &block) ⇒ Object
Returns content block if used as an attribute reader (no args) Otherwise, if a block is passed, it adds it as content to this Glimmer web component
316
317
318
319
320
321
322
323
324
325
326
327
|
# File 'lib/glimmer/web/component.rb', line 316
def content(*args, &block)
if args.empty?
if block_given?
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Web::ComponentExpression.new, self.class.keyword, &block)
else
@content
end
else
super
end
end
|
#data_bind(property, model_binding) ⇒ Object
306
307
308
|
# File 'lib/glimmer/web/component.rb', line 306
def data_bind(property, model_binding)
@markup_root&.data_bind(property, model_binding)
end
|
#get_attribute(attribute_name) ⇒ Object
285
286
287
288
289
290
291
|
# File 'lib/glimmer/web/component.rb', line 285
def get_attribute(attribute_name)
if has_instance_method?(attribute_name)
send(attribute_name)
else
@markup_root.get_attribute(attribute_name)
end
end
|
#handle_observation_request(observation_request, block) ⇒ Object
242
243
244
245
246
247
248
249
250
|
# File 'lib/glimmer/web/component.rb', line 242
def handle_observation_request(observation_request, block)
observation_request = observation_request.to_s
if observation_request.start_with?('on_updated_')
property = observation_request.sub(/^on_updated_/, '') add_observer(DataBinding::Observer.proc(&block), property) if can_add_observer?(property)
else
markup_root.handle_observation_request(observation_request, block)
end
end
|
#has_attribute?(attribute_name, *args) ⇒ Boolean
264
265
266
267
|
# File 'lib/glimmer/web/component.rb', line 264
def has_attribute?(attribute_name, *args)
has_instance_method?(attribute_setter(attribute_name)) ||
@markup_root.has_attribute?(attribute_name, *args)
end
|
#has_instance_method?(method_name) ⇒ Boolean
This method ensures it has an instance method not coming from Glimmer DSL
278
279
280
281
282
283
|
# File 'lib/glimmer/web/component.rb', line 278
def has_instance_method?(method_name)
respond_to?(method_name) and
!markup_root&.respond_to?(method_name) and
!method(method_name)&.source_location&.first&.include?('glimmer/dsl/engine.rb') and
!method(method_name)&.source_location&.first&.include?('glimmer/web/element_proxy.rb')
end
|
#initialize(parent, args, options, &content) ⇒ Object
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/glimmer/web/component.rb', line 182
def initialize(parent, args, options, &content)
Component.interpretation_stack.push(self)
@parent = parent
options = args.delete_at(-1) if args.is_a?(Array) && args.last.is_a?(Hash)
if args.is_a?(Hash)
options = args
args = []
end
options ||= {}
@args = args
options ||= {}
@options = self.class.options.merge(options)
@content = Util::ProcTracker.new(content) if content
execute_hooks('before_render')
markup_block = self.class.instance_variable_get("@markup_block")
raise Glimmer::Error, 'Invalid Glimmer web component for having no markup! Please define markup block!' if markup_block.nil?
@markup_root = instance_exec(&markup_block)
@markup_root.options[:parent] = options[:parent] if !options[:parent].nil?
@parent ||= @markup_root.parent
raise Glimmer::Error, 'Invalid Glimmer web component for having an empty markup! Please fill markup block!' if @markup_root.nil?
if options[:render] != false
execute_hooks('after_render')
else
on_render_listener = proc { execute_hooks('after_render') }
@markup_root.handle_observation_request('on_render', on_render_listener)
end
observer_registration_cleanup_listener = proc do
observer_registrations.compact.each(&:deregister)
observer_registrations.clear
end
@markup_root.handle_observation_request('on_remove', observer_registration_cleanup_listener)
post_add_content if content.nil?
end
|
#local_respond_to? ⇒ Object
339
|
# File 'lib/glimmer/web/component.rb', line 339
alias local_respond_to? respond_to_missing?
|
#observer_registrations ⇒ Object
This stores observe keyword registrations of model/attribute observers
228
229
230
|
# File 'lib/glimmer/web/component.rb', line 228
def observer_registrations
@observer_registrations ||= []
end
|
#post_add_content ⇒ Object
#post_initialize_child(child) ⇒ Object
Subclasses may override to perform post initialization work on an added child
219
220
221
|
# File 'lib/glimmer/web/component.rb', line 219
def post_initialize_child(child)
end
|
#remove ⇒ Object
302
303
304
|
# File 'lib/glimmer/web/component.rb', line 302
def remove
@markup_root&.remove
end
|
#render(parent: nil, custom_parent_dom_element: nil, brand_new: false) ⇒ Object
297
298
299
300
|
# File 'lib/glimmer/web/component.rb', line 297
def render(parent: nil, custom_parent_dom_element: nil, brand_new: false)
@markup_root&.render(parent: parent, custom_parent_dom_element: custom_parent_dom_element, brand_new: brand_new)
end
|
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
340
341
342
343
344
|
# File 'lib/glimmer/web/component.rb', line 340
def respond_to_missing?(method_name, include_private = false)
super(method_name, include_private) or
can_handle_observation_request?(method_name) or
markup_root.respond_to?(method_name, include_private)
end
|
#set_attribute(attribute_name, *args) ⇒ Object
269
270
271
272
273
274
275
|
# File 'lib/glimmer/web/component.rb', line 269
def set_attribute(attribute_name, *args)
if has_instance_method?(attribute_setter(attribute_name))
send(attribute_setter(attribute_name), *args)
else
@markup_root.set_attribute(attribute_name, *args)
end
end
|