class Volt::AttributeBinding
Public Class Methods
new(volt_app, target, context, binding_name, attribute_name, getter, setter)
click to toggle source
Calls superclass method
# File lib/volt/page/bindings/attribute_binding.rb, line 6 def initialize(volt_app, target, context, binding_name, attribute_name, getter, setter) super(volt_app, target, context, binding_name) @attribute_name = attribute_name @getter = getter @setter = setter setup end
Public Instance Methods
changed(event = nil)
click to toggle source
# File lib/volt/page/bindings/attribute_binding.rb, line 65 def changed(event = nil) case @attribute_name when 'value' current_value = `#{element}.val() || ''` else current_value = `#{element}.is(':checked')` end if @is_radio if current_value # if it is a radio button and its checked @context.instance_exec(@selected_value, &@setter) end else @context.instance_exec(current_value, &@setter) end end
element()
click to toggle source
# File lib/volt/page/bindings/attribute_binding.rb, line 83 def element @element ||= `$('#' + #{binding_name})` end
invalidate()
click to toggle source
On select boxes, when an option is added/changed, we want to run update again. By calling invalidate, it will run at most once on the next tick.
# File lib/volt/page/bindings/attribute_binding.rb, line 140 def invalidate @computation.invalidate! end
remove()
click to toggle source
# File lib/volt/page/bindings/attribute_binding.rb, line 152 def remove # Unbind events, leave the element there since attribute bindings # aren't responsible for it being there. case @attribute_name when 'value' if @is_select `#{element}.off('change.attrbind')` `#{element}.off('invalidate')` elsif @is_hidden `#{element}.unwatch('value')` else `#{element}.off('input.attrbind', #{nil})` end when 'checked' `#{element}.off('change.attrbind', #{nil})` end if @computation @computation.stop @computation = nil end @string_template_renderer.remove if @string_template_renderer @string_template_renderer_computation.stop if @string_template_renderer_computation # Clear any references @target = nil @context = nil @getter = nil end
remove_anchors()
click to toggle source
# File lib/volt/page/bindings/attribute_binding.rb, line 183 def remove_anchors fail 'attribute bindings do not have anchors, can not remove them' end
setup()
click to toggle source
# File lib/volt/page/bindings/attribute_binding.rb, line 16 def setup if `#{element}.is('select')` @is_select = true elsif `#{element}.is('[type=hidden]')` @is_hidden = true elsif `#{element}.is('[type=radio]')` @is_radio = true @selected_value = `#{element}.attr('value') || ''` elsif `#{element}.is('option')` @is_option = true end if @is_option else # Bind so when this value updates, we update case @attribute_name when 'value' changed_event = Proc.new { changed } if @is_select `#{element}.on('change.attrbind', #{changed_event})` invalidate_proc = Proc.new { invalidate } `#{element}.on('invalidate', #{invalidate_proc})` elsif @is_hidden `#{element}.watch('value', #{changed_event})` else `#{element}.on('input.attrbind', #{changed_event})` end when 'checked' changed_event = proc { |event| changed(event) } `#{element}.on('change.attrbind', #{changed_event})` end end # Listen for changes @computation = lambda do begin @context.instance_eval(&@getter) rescue => e getter_fail(e) '' end end.watch_and_resolve!( method(:update), method(:getter_fail) ) end
update(new_value)
click to toggle source
# File lib/volt/page/bindings/attribute_binding.rb, line 87 def update(new_value) if @attribute_name == 'checked' update_checked(new_value) return end # Stop any previous reactive template computations @string_template_renderer_computation.stop if @string_template_renderer_computation @string_template_renderer.remove if @string_template_renderer if new_value.is_a?(StringTemplateRenderer) # We don't need to refetch the whole reactive template to # update, we can just depend on it and update directly. @string_template_renderer = new_value @string_template_renderer_computation = lambda do self.value = @string_template_renderer.html end.watch! else new_value = '' if new_value.is_a?(NilMethodCall) || new_value.nil? self.value = new_value end end
update_checked(value)
click to toggle source
# File lib/volt/page/bindings/attribute_binding.rb, line 144 def update_checked(value) value = false if value.is_a?(NilMethodCall) || value.nil? value = (@selected_value == value) if @is_radio `#{element}.prop('checked', #{value})` end
value=(val)
click to toggle source
# File lib/volt/page/bindings/attribute_binding.rb, line 112 def value=(val) case @attribute_name when 'value' if @is_option # When a new option is added, we trigger the invalidate event on the # parent select so it will re-run update on the next tick and set # the correct option. `#{element}.parent('select').trigger('invalidate');` end # TODO: only update if its not the same, this keeps it from moving the # cursor in text fields. `#{element}.val(#{val})` if val != `(#{element}.val() || '')` when 'disabled' # Disabled is handled specially, you can either return a boolean: # (true being disabled, false not disabled), or you can optionally # include the "disabled" string. (or any string) if val != false && val.present? `#{element}.attr('disabled', 'disabled')` else `#{element}.removeAttr('disabled')` end else `#{element}.attr(#{@attribute_name}, #{val})` end end