Class: Dommy::HTMLInputElement

Inherits:
HTMLElement show all
Defined in:
lib/dommy/html_elements.rb

Overview

‘<input>` — covers the most-used form control surface.

Constant Summary

Constants inherited from Element

Element::ATTRIBUTE_NODE, Element::CDATA_SECTION_NODE, Element::COMMENT_NODE, Element::DOCUMENT_FRAGMENT_NODE, Element::DOCUMENT_NODE, Element::DOCUMENT_POSITION_CONTAINED_BY, Element::DOCUMENT_POSITION_CONTAINS, Element::DOCUMENT_POSITION_DISCONNECTED, Element::DOCUMENT_POSITION_FOLLOWING, Element::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, Element::DOCUMENT_POSITION_PRECEDING, Element::DOCUMENT_TYPE_NODE, Element::ELEMENT_NODE, Element::HTML_NAMESPACE, Element::PROCESSING_INSTRUCTION_NODE, Element::REFLECTED_TOKEN_LIST_HOSTS, Element::SHADOW_HOST_TAGS, Element::SVG_NAMESPACE, Element::TEXT_NODE

Constants included from Node

Node::ATTRIBUTE_NODE, Node::CDATA_SECTION_NODE, Node::COMMENT_NODE, Node::DOCUMENT_FRAGMENT_NODE, Node::DOCUMENT_NODE, Node::DOCUMENT_POSITION_CONTAINED_BY, Node::DOCUMENT_POSITION_CONTAINS, Node::DOCUMENT_POSITION_DISCONNECTED, Node::DOCUMENT_POSITION_FOLLOWING, Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, Node::DOCUMENT_POSITION_PRECEDING, Node::DOCUMENT_TYPE_NODE, Node::ELEMENT_NODE, Node::HTML_NAMESPACE, Node::PROCESSING_INSTRUCTION_NODE, Node::TEXT_NODE

Instance Attribute Summary

Attributes inherited from Element

#document

Instance Method Summary collapse

Methods inherited from HTMLElement

#case_sensitive_attribute_names?

Methods included from Internal::ReflectedAttributes

included

Methods inherited from Element

#[], #[]=, #__dommy_backend_node__, #__internal_set_namespace__, #__internal_shadow_root__, #__test_scroll_log__, #access_key_label, #after, #anchor_href, #animate, #aria_content_attr, #aria_element_attr, #aria_element_get, #aria_element_set, #aria_elements_attr, #aria_elements_get, #aria_elements_set, #aria_find_in_root, #aria_get, #aria_set, #at_xpath, #attach_shadow, #attributes, #base_uri, #before, #blur, #child_element_count, #child_nodes, #children, #class_list, #class_name, #class_name=, #clear_aria_element_ref_for, #click, #clone_node, #closest, #contains?, #dataset, #element_prefix, #equal_node?, #first_child, #first_element_child, #focus, #get_animations, #get_attribute, #get_attribute_names, #get_attribute_node, #get_attribute_node_ns, #get_attribute_ns, #get_bounding_client_rect, #get_client_rects, #get_elements_by_class_name, #get_elements_by_tag_name, #get_elements_by_tag_name_ns, #get_html, #get_inner_html, #has_attribute?, #has_attribute_ns?, #has_attributes?, #has_child_nodes?, #hide_popover, #id, #id=, #initialize, #inner_html, #inner_html=, #insert_adjacent_element, #insert_adjacent_html, #insert_adjacent_text, #insert_before, #insertion_parent!, #is_connected?, #last_child, #last_element_child, #live_child_nodes, #local_name, #matches?, #namespace_uri, #next_element_sibling, #next_sibling, #normalize, #on, #outer_html, #outer_html=, #owner_document, #parent_element, #parent_node, #path, #previous_element_sibling, #previous_sibling, #query_selector, #query_selector_all, #reflected_attr_name, #reflected_token_list, #remove, #remove_attribute, #remove_attribute_node, #remove_attribute_ns, #remove_child, #replace_child, #replace_with_nodes, #request_fullscreen, #role, #role=, #root_node, #same_node?, #scoped_query, #set_attribute, #set_attribute_node, #set_attribute_ns, #shadow_root, #show_popover, #slot, #slot=, #style, #tag_name, #text_content, #text_content=, #to_s, #toggle_attribute, #toggle_popover, #with_selector_errors, #xpath

Methods included from Bridge::Methods

included

Methods included from Internal::ParentNode

#append, #append_child, #prepend, #replace_children

Methods included from Node

#compare_document_position, #get_root_node, #is_default_namespace, #is_equal_node, #is_same_node, #lookup_namespace_uri, #lookup_prefix

Methods included from EventTarget

#__internal_deliver_event__, #__internal_event_parent__, #add_event_listener, capture_flag, #deliver_at, #dispatch_event, js_truthy?, #remove_event_listener

Constructor Details

This class inherits a constructor from Dommy::Element

Instance Method Details

#__driver_set_files__(files_input) ⇒ Object

Test-only seam: set the input’s file list directly. Accepts an array (wrapped in a FileList) or a FileList itself.



255
256
257
# File 'lib/dommy/html_elements.rb', line 255

def __driver_set_files__(files_input)
  @__files = files_input.is_a?(FileList) ? files_input : FileList.new(Array(files_input))
end

#__js_call__(method, args) ⇒ Object



427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
# File 'lib/dommy/html_elements.rb', line 427

def __js_call__(method, args)
  case method
  when "select"
    select
  when "setSelectionRange"
    set_selection_range(args[0], args[1], args[2])
  when "setRangeText"
    set_range_text(args[0])
  when "stepUp"
    step_up(args[0])
  when "stepDown"
    step_down(args[0])
  when "checkValidity"
    check_validity
  when "reportValidity"
    report_validity
  when "setCustomValidity"
    set_custom_validity(args[0])
  else
    super
  end
end

#__js_get__(key) ⇒ Object



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'lib/dommy/html_elements.rb', line 381

def __js_get__(key)
  case key
  when "type"
    type
  when "value"
    value
  when "checked"
    checked
  when "readonly", "readOnly"
    readonly
  when "labels"
    labels
  when "form"
    form
  when "validity"
    validity
  when "willValidate"
    will_validate
  when "validationMessage"
    validation_message
  when "files"
    files
  else
    super
  end
end

#__js_set__(key, value) ⇒ Object



408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/dommy/html_elements.rb', line 408

def __js_set__(key, value)
  case key
  when "type"
    set_reflected_string("type", value)
  when "value"
    self.value = value
  when "checked"
    self.checked = value
  when "readonly", "readOnly"
    self.readonly = value
  else
    super
  end
end

#check_validityObject



366
367
368
369
370
# File 'lib/dommy/html_elements.rb', line 366

def check_validity
  ok = !will_validate || validity.valid
  dispatch_event(Event.new("invalid", "bubbles" => false, "cancelable" => true)) unless ok
  ok
end

#checkedObject



299
300
301
# File 'lib/dommy/html_elements.rb', line 299

def checked
  @__checked.nil? ? default_checked : @__checked
end

#checked=(v) ⇒ Object



303
304
305
# File 'lib/dommy/html_elements.rb', line 303

def checked=(v)
  @__checked = !!v
end

#filesObject

‘files` — for `<input type=“file”>`. Browsers populate this via user interaction; in tests, code uses `driver_set_files` to seed it.



249
250
251
# File 'lib/dommy/html_elements.rb', line 249

def files
  @__files ||= FileList.new
end

#formObject

Closest enclosing form (or nil if detached / not in a form).



314
315
316
# File 'lib/dommy/html_elements.rb', line 314

def form
  closest("form")
end

#labelsObject



307
308
309
310
311
# File 'lib/dommy/html_elements.rb', line 307

def labels
  return [] if id.empty?

  @document.query_selector_all("label[for='#{id}']")
end

#raw_valueObject

Underlying string the user supplied to ‘value=`, before any sanitization. Used by ValidityState.badInput so a non-parseable number still trips constraint validation.



295
296
297
# File 'lib/dommy/html_elements.rb', line 295

def raw_value
  @__raw_value || @__value || reflected_string("value")
end

#report_validityObject



372
373
374
# File 'lib/dommy/html_elements.rb', line 372

def report_validity
  check_validity
end

#sanitize_number(raw) ⇒ Object



284
285
286
287
288
289
290
# File 'lib/dommy/html_elements.rb', line 284

def sanitize_number(raw)
  s = raw.to_s
  Float(s)
  s
rescue ArgumentError, TypeError
  ""
end

#sanitize_value(raw) ⇒ Object

Spec: the “value sanitization algorithm” runs lazily on read. type=email/url trim leading/trailing ASCII whitespace; type=number rejects non-finite floats by returning “” (badInput stays true so validity surfaces the original raw value).



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/dommy/html_elements.rb', line 263

def sanitize_value(raw)
  case type
  when "email"
    if @__node__.key?("multiple")
      raw.to_s.split(",").map(&:strip).join(",")
    else
      raw.to_s.strip
    end

  when "url"
    raw.to_s.strip
  when "number", "range"
    sanitize_number(raw)
  when "color"
    s = raw.to_s.strip.downcase
    s.match?(/\A#[0-9a-f]{6}\z/) ? s : "#000000"
  else
    raw.to_s
  end
end

#selectObject

No real text selection; method stubs let callers proceed.



319
320
321
# File 'lib/dommy/html_elements.rb', line 319

def select
  nil
end

#set_custom_validity(msg) ⇒ Object



376
377
378
379
# File 'lib/dommy/html_elements.rb', line 376

def set_custom_validity(msg)
  @custom_validity_message = msg.to_s
  nil
end

#set_range_text(_replacement, *_) ⇒ Object



327
328
329
# File 'lib/dommy/html_elements.rb', line 327

def set_range_text(_replacement, *_)
  nil
end

#set_selection_range(_start, _end, _direction = nil) ⇒ Object



323
324
325
# File 'lib/dommy/html_elements.rb', line 323

def set_selection_range(_start, _end, _direction = nil)
  nil
end

#step_down(_n = 1) ⇒ Object



335
336
337
# File 'lib/dommy/html_elements.rb', line 335

def step_down(_n = 1)
  nil
end

#step_up(_n = 1) ⇒ Object



331
332
333
# File 'lib/dommy/html_elements.rb', line 331

def step_up(_n = 1)
  nil
end

#typeObject

Own js_call methods, on top of Element’s.



224
225
226
227
# File 'lib/dommy/html_elements.rb', line 224

def type
  raw = @__node__["type"].to_s
  raw.empty? ? "text" : raw.downcase
end

#type=(v) ⇒ Object



229
230
231
# File 'lib/dommy/html_elements.rb', line 229

def type=(v)
  set_reflected_string("type", v)
end

#validation_messageObject



353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/dommy/html_elements.rb', line 353

def validation_message
  return "" unless will_validate

  msg = (@custom_validity_message || "").to_s
  return msg unless msg.empty?
  return "Please fill out this field." if validity.value_missing
  return "Please match the requested format." if validity.pattern_mismatch
  return "Please enter a valid email address." if validity.type_mismatch && type == "email"
  return "Please enter a URL." if validity.type_mismatch && type == "url"

  ""
end

#validityObject



339
340
341
# File 'lib/dommy/html_elements.rb', line 339

def validity
  @__validity ||= ValidityState.new(self)
end

#valueObject

Runtime value/checked. Dommy has no UI, so the runtime state is initialized from the attribute on first access and tracked separately thereafter — matching browser semantics where the ‘value` IDL attribute can drift from the `value` content attr.



237
238
239
# File 'lib/dommy/html_elements.rb', line 237

def value
  sanitize_value(@__value.nil? ? reflected_string("value") : @__value)
end

#value=(v) ⇒ Object



241
242
243
244
245
# File 'lib/dommy/html_elements.rb', line 241

def value=(v)
  raw = v.to_s
  @__raw_value = raw
  @__value = raw
end

#will_validateObject

Whether this control participates in constraint validation. Disabled / hidden / button-type inputs return false.



345
346
347
348
349
350
351
# File 'lib/dommy/html_elements.rb', line 345

def will_validate
  return false if reflected_boolean("disabled")
  return false if reflected_boolean("readonly")
  return false if %w[hidden button submit reset image].include?(type)

  true
end