class Hyalite::DOMComponent

Attributes

root_node_id[R]

Public Class Methods

new(element) click to toggle source
# File lib/hyalite/dom_component.rb, line 13
def initialize(element)
  @element = element
  @tag = @element.type.downcase
  @input_wrapper = InputWrapper.new(self)
end

Public Instance Methods

current_element() click to toggle source
# File lib/hyalite/dom_component.rb, line 19
def current_element
  @element
end
mount_component(root_id, mount_ready, context) click to toggle source
# File lib/hyalite/dom_component.rb, line 23
def mount_component(root_id, mount_ready, context)
  return if @tag == "noscript"
  @root_node_id = root_id

  props = current_element.props

  case @tag
  # when 'iframe', 'img', 'form', 'video', 'audio'
  #   this._wrapperState = {
  #     listeners: null,
  #   }
  #   transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
  # when 'button'
  #   props = ReactDOMButton.getNativeProps(this, props, nativeParent);
  when 'input'
    @input_wrapper.mount_wrapper
    props = @input_wrapper.native_props
  # when 'option'
  #   ReactDOMOption.mountWrapper(this, props, nativeParent);
  #   props = ReactDOMOption.getNativeProps(this, props);
  # when 'select'
  #   ReactDOMSelect.mountWrapper(this, props, nativeParent);
  #   props = ReactDOMSelect.getNativeProps(this, props);
  #   transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
  # when 'textarea'
  #   ReactDOMTextarea.mountWrapper(this, props, nativeParent);
  #   props = ReactDOMTextarea.getNativeProps(this, props);
  #   transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
  end

  markup = create_open_tag_markup_and_put_listeners(mount_ready, @element.props)
  create_content_markup(mount_ready, markup, context)
end
public_instance() click to toggle source
# File lib/hyalite/dom_component.rb, line 125
def public_instance
  native_node
end
receive_component(next_element, mount_ready, context) click to toggle source
# File lib/hyalite/dom_component.rb, line 82
def receive_component(next_element, mount_ready, context)
  prev_element = @element
  @element = next_element
  update_component(mount_ready, prev_element, next_element, context);
end
to_s() click to toggle source
# File lib/hyalite/dom_component.rb, line 129
def to_s
  {
    tag: @tag,
    root_node_id: root_node_id,
    rendered_children: @rendered_children,
  }.to_s
end
unmount_component() click to toggle source
# File lib/hyalite/dom_component.rb, line 57
def unmount_component
  case @tag
  # when 'iframe', 'img', 'form'
  #   listeners = this._wrapperState.listeners;
  #   if (listeners) {
  #     for (var i = 0; i < listeners.length; i++) {
  #       listeners[i].remove();
  #     }
  #   }
  when 'input'
    @input_wrapper.unmount_wrapper
  end

  unmount_children
  BrowserEvent.delete_all_listeners(@root_node_id)
  Mount.purge_id(@root_node_id)
  @root_node_id = nil
  # @wrapper_state = null;
  if @node_with_legacy_properties
    node = @node_with_legacy_properties
    node.internal_component = nil
    @node_with_legacy_properties = nil
  end
end
update_component(mount_ready, prev_element, next_element, context) click to toggle source
# File lib/hyalite/dom_component.rb, line 88
def update_component(mount_ready, prev_element, next_element, context)
  last_props = prev_element.props
  next_props = @element.props

  case @tag
  # when 'button':
  #   lastProps = ReactDOMButton.getNativeProps(this, lastProps);
  #   nextProps = ReactDOMButton.getNativeProps(this, nextProps);
  when 'input'
    @input_wrapper.update_wrapper
    last_props = @input_wrapper.native_props(last_props)
  #   nextProps = ReactDOMInput.getNativeProps(this, nextProps);
  # when 'option':
  #   lastProps = ReactDOMOption.getNativeProps(this, lastProps);
  #   nextProps = ReactDOMOption.getNativeProps(this, nextProps);
  # when 'select':
  #   lastProps = ReactDOMSelect.getNativeProps(this, lastProps);
  #   nextProps = ReactDOMSelect.getNativeProps(this, nextProps);
  # when 'textarea':
  #   ReactDOMTextarea.updateWrapper(this);
  #   lastProps = ReactDOMTextarea.getNativeProps(this, lastProps);
  #   nextProps = ReactDOMTextarea.getNativeProps(this, nextProps);
  end

  # assertValidProps(this, nextProps);
  update_dom_properties(last_props, next_props, mount_ready)
  update_dom_children(last_props, next_props, mount_ready, context)

  # if (!canDefineProperty && this._nodeWithLegacyProperties) {
  #   this._nodeWithLegacyProperties.props = nextProps;
  # }

  if @tag == 'select'
    mount_ready.enqueue { post_update_select_wrapper }
  end
end

Private Instance Methods

create_content_markup(mount_ready, markup, context) click to toggle source
# File lib/hyalite/dom_component.rb, line 280
def create_content_markup(mount_ready, markup, context)
  children = @element.props[:children]

  inner_html = @element.props[:dangerouslySetInnerHTML]
  if inner_html
    if inner_html.has_key?(:__html)
      markup.inner_html = inner_html[:__html]
    end
  elsif is_text_content(children)
    markup.text = children.to_s
  else
    mount_images = mount_children(children, mount_ready, context)
    mount_images.compact.each do |image|
      if is_text_content(image)
        markup << Hyalite::DOM::Text.new(image.to_s)
      else
        markup << image
      end
    end
  end
  markup
end
create_open_tag_markup_and_put_listeners(mount_ready, props) click to toggle source
# File lib/hyalite/dom_component.rb, line 250
def create_open_tag_markup_and_put_listeners(mount_ready, props)
  element = $document.create_element(@tag)

  props.each do |prop_key, prop_value|
    next unless prop_value

    if BrowserEvent.include?(prop_key)
      enqueue_put_listener(@root_node_id, prop_key, prop_value, mount_ready)
    else
      if prop_key == :style
        if prop_value
          prop_value = @previous_style_copy = props[:style].clone
        end
        DOMPropertyOperations.create_markup_for_styles(element, prop_value)
      else
        if is_custom_component(@tag, props)
          DOMPropertyOperations.create_markup_for_custom_attribute(element, prop_key, prop_value)
        else
          DOMPropertyOperations.create_markup_for_property(element, prop_key, prop_value)
        end
      end
    end
  end

  #return element if mount_ready.render_to_static_markup

  element.attributes[Mount::ID_ATTR_NAME] = @root_node_id
  element
end
enqueue_put_listener(id, event_name, listener, mount_ready) click to toggle source
# File lib/hyalite/dom_component.rb, line 303
def enqueue_put_listener(id, event_name, listener, mount_ready)
  container = Mount.container_for_id(id)
  if container
    doc = container.element? ? container.document : container
    BrowserEvent.listen_to(event_name, doc)
  end
  mount_ready.enqueue do
    BrowserEvent.put_listener(id, event_name, listener)
  end
end
is_custom_component(tag, props) click to toggle source
# File lib/hyalite/dom_component.rb, line 314
def is_custom_component(tag, props)
  tag.include?('-') || props.has_key?(:is)
end
is_text_content(children) click to toggle source
# File lib/hyalite/dom_component.rb, line 318
def is_text_content(children)
  case children
  when String, Numeric
    true
  else
    false
  end
end
native_node() click to toggle source
# File lib/hyalite/dom_component.rb, line 139
def native_node
  @native_node ||= Mount.node(@root_node_id)
end
update_dom_children(last_props, next_props, mount_ready, context) click to toggle source
# File lib/hyalite/dom_component.rb, line 219
def update_dom_children(last_props, next_props, mount_ready, context)
  last_content = last_props[:children] if is_text_content(last_props[:children])
  next_content = next_props[:children] if is_text_content(next_props[:children])

  last_html = last_props[:dangerouslySetInnerHTML].try {|_| _['__html'] }
  next_html = next_props[:dangerouslySetInnerHTML].try {|_| _['__html'] }

  last_children = last_props[:children] unless last_content
  next_children = next_props[:children] unless next_content

  last_has_content_or_html = !last_content.nil? || !last_html.nil?
  next_has_content_or_html = !next_content.nil? || !next_html.nil?
  if last_children && next_children.nil?
    update_children(nil, mount_ready, context)
  elsif last_has_content_or_html && !next_has_content_or_html
    update_text_content('')
  end

  if next_content
    unless last_content == next_content
      update_text_content(next_content.to_s)
    end
  elsif next_html
    unless last_html == next_html
      update_markup(next_html.to_s)
    end
  elsif next_children
    update_children(next_children, mount_ready, context)
  end
end
update_dom_properties(last_props, next_props, mount_ready) click to toggle source
# File lib/hyalite/dom_component.rb, line 143
def update_dom_properties(last_props, next_props, mount_ready)
  style_updates = {}

  last_props.each do |prop_key, prop_value|
    next if next_props.has_key?(prop_key)

    if prop_key == :style
      @previous_style_copy.each do |style_name, style|
        style_updates[style_name] = ''
      end

      @previous_style_copy = nil
    elsif BrowserEvent.include?(prop_key)
      if last_props.has_key? prop_key
        BrowserEvent.delete_listener(root_node_id, prop_key)
      end
    elsif DOMProperty.include?(prop_key) || DOMProperty.is_custom_attribute(prop_key)
      node = Mount.node(root_node_id)
      DOMPropertyOperations.delete_value_for_property(node, prop_key, prop_value)
    end
  end

  next_props.each do |prop_key, next_prop|
    last_prop = prop_key == :style ? @previous_style_copy : last_props[prop_key]
    next if next_prop == last_prop

    if prop_key == :style
      if next_prop
        next_prop = @previous_style_copy = next_prop.clone
      else
        @previous_style_copy = nil
      end

      if last_prop
        last_prop.each do |style_name, style|
          unless next_prop.has_key?(style_name)
            style_updates[style_name] = ''
          end
        end

        next_prop.each do |style_name, style|
          if next_prop.has_key?(style_name) && last_prop[style_name] != next_prop[style_name]
            style_updates[style_name] = next_prop[style_name]
          end
        end
      else
        style_updates = next_prop
      end
    elsif BrowserEvent.include?(prop_key)
      if next_prop
        enqueue_put_listener(root_node_id, prop_key, next_prop, mount_ready)
      elsif last_prop
        BrowserEvent.delete_listener(root_node_id, prop_key)
      end
    elsif is_custom_component(@tag, next_props)
      node = Mount.node(root_node_id)
      DOMPropertyOperations.set_value_for_attribute(node, prop_key, next_prop);
    elsif DOMProperty.include?(prop_key) || DOMProperty.is_custom_attribute(prop_key)
      node = Mount.node(root_node_id)
      if next_prop
        DOMPropertyOperations.set_value_for_property(node, prop_key, next_prop);
      else
        DOMPropertyOperations.delete_value_for_property(node, prop_key)
      end
    end
  end

  if style_updates.any?
    node = Mount.node(root_node_id)
    node.style(style_updates)
  end
rescue => e
    p e
  raise
end