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::PROCESSING_INSTRUCTION_NODE, Element::SHADOW_HOST_TAGS, 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::PROCESSING_INSTRUCTION_NODE, Node::TEXT_NODE

Instance Attribute Summary

Attributes inherited from Element

#__node__, #document

Instance Method Summary collapse

Methods inherited from Element

#[], #[]=, #__shadow_root__, #after, #anchor_href, #append, #append_child, #attach_shadow, #attributes, #base_uri, #before, #blur, #child_element_count, #child_nodes, #children, #class_list, #class_name, #class_name=, #click, #clone_node, #closest, #compare_document_position, #contains?, #dataset, #equal_node?, #first_child, #first_element_child, #focus, #get_attribute, #get_attribute_node, #get_elements_by_class_name, #get_elements_by_tag_name, #get_html, #get_inner_html, #has_attribute?, #has_attributes?, #has_child_nodes?, #id, #id=, #initialize, #inner_html, #inner_html=, #insert_adjacent_element, #insert_adjacent_html, #insert_adjacent_text, #insert_before, #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, #prepend, #previous_element_sibling, #previous_sibling, #query_selector, #query_selector_all, #reflected_attr_name, #remove, #remove_attribute, #remove_attribute_node, #remove_child, #replace_child, #replace_children, #replace_with_nodes, #role, #role=, #root_node, #same_node?, #set_attribute, #set_attribute_node, #shadow_root, #slot, #slot=, #style, #tag_name, #text_content, #text_content=, #to_s, #toggle_attribute

Methods included from EventTarget

#__deliver_event__, #add_event_listener, #dispatch_event, #invoke_listener, #remove_event_listener

Constructor Details

This class inherits a constructor from Dommy::Element

Instance Method Details

#__js_call__(method, args) ⇒ Object



671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
# File 'lib/dommy/html_elements.rb', line 671

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



593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
# File 'lib/dommy/html_elements.rb', line 593

def __js_get__(key)
  case key
  when "type"
    type
  when "name"
    name
  when "placeholder"
    placeholder
  when "min"
    min
  when "max"
    max
  when "step"
    step
  when "pattern"
    pattern
  when "autocomplete"
    autocomplete
  when "autofocus"
    autofocus
  when "defaultValue"
    default_value
  when "defaultChecked"
    default_checked
  when "value"
    value
  when "checked"
    checked
  when "disabled"
    disabled
  when "required"
    required
  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



644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
# File 'lib/dommy/html_elements.rb', line 644

def __js_set__(key, value)
  case key
  when "type"
    set_reflected_string("type", value)
  when "name"
    set_reflected_string("name", value)
  when "placeholder"
    set_reflected_string("placeholder", value)
  when "min", "max", "step", "pattern", "autocomplete"
    set_reflected_string(key, value)
  when "autofocus"
    set_reflected_boolean("autofocus", value)
  when "value"
    self.value = value
  when "checked"
    self.checked = value
  when "disabled"
    self.disabled = value
  when "required"
    self.required = value
  when "readonly", "readOnly"
    self.readonly = value
  else
    super
  end
end

#__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.



443
444
445
# File 'lib/dommy/html_elements.rb', line 443

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

#autocompleteObject



401
402
403
# File 'lib/dommy/html_elements.rb', line 401

def autocomplete
  reflected_string("autocomplete")
end

#autofocusObject



405
406
407
# File 'lib/dommy/html_elements.rb', line 405

def autofocus
  reflected_boolean("autofocus")
end

#autofocus=(v) ⇒ Object



409
410
411
# File 'lib/dommy/html_elements.rb', line 409

def autofocus=(v)
  set_reflected_boolean("autofocus", v)
end

#check_validityObject



578
579
580
581
582
# File 'lib/dommy/html_elements.rb', line 578

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

#checkedObject



487
488
489
# File 'lib/dommy/html_elements.rb', line 487

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

#checked=(v) ⇒ Object



491
492
493
# File 'lib/dommy/html_elements.rb', line 491

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

#default_checkedObject



417
418
419
# File 'lib/dommy/html_elements.rb', line 417

def default_checked
  reflected_boolean("checked")
end

#default_valueObject



413
414
415
# File 'lib/dommy/html_elements.rb', line 413

def default_value
  reflected_string("value")
end

#disabledObject



495
496
497
# File 'lib/dommy/html_elements.rb', line 495

def disabled
  reflected_boolean("disabled")
end

#disabled=(v) ⇒ Object



499
500
501
# File 'lib/dommy/html_elements.rb', line 499

def disabled=(v)
  set_reflected_boolean("disabled", v)
end

#filesObject

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



437
438
439
# File 'lib/dommy/html_elements.rb', line 437

def files
  @__files ||= FileList.new
end

#formObject

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



526
527
528
# File 'lib/dommy/html_elements.rb', line 526

def form
  closest("form")
end

#labelsObject



519
520
521
522
523
# File 'lib/dommy/html_elements.rb', line 519

def labels
  return [] if id.empty?

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

#maxObject



389
390
391
# File 'lib/dommy/html_elements.rb', line 389

def max
  reflected_string("max")
end

#minObject



385
386
387
# File 'lib/dommy/html_elements.rb', line 385

def min
  reflected_string("min")
end

#nameObject



369
370
371
# File 'lib/dommy/html_elements.rb', line 369

def name
  reflected_string("name")
end

#name=(v) ⇒ Object



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

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

#patternObject



397
398
399
# File 'lib/dommy/html_elements.rb', line 397

def pattern
  reflected_string("pattern")
end

#placeholderObject



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

def placeholder
  reflected_string("placeholder")
end

#placeholder=(v) ⇒ Object



381
382
383
# File 'lib/dommy/html_elements.rb', line 381

def placeholder=(v)
  set_reflected_string("placeholder", v)
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.



483
484
485
# File 'lib/dommy/html_elements.rb', line 483

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

#readonlyObject



511
512
513
# File 'lib/dommy/html_elements.rb', line 511

def readonly
  reflected_boolean("readonly")
end

#readonly=(v) ⇒ Object



515
516
517
# File 'lib/dommy/html_elements.rb', line 515

def readonly=(v)
  set_reflected_boolean("readonly", v)
end

#report_validityObject



584
585
586
# File 'lib/dommy/html_elements.rb', line 584

def report_validity
  check_validity
end

#requiredObject



503
504
505
# File 'lib/dommy/html_elements.rb', line 503

def required
  reflected_boolean("required")
end

#required=(v) ⇒ Object



507
508
509
# File 'lib/dommy/html_elements.rb', line 507

def required=(v)
  set_reflected_boolean("required", v)
end

#sanitize_number(raw) ⇒ Object



472
473
474
475
476
477
478
# File 'lib/dommy/html_elements.rb', line 472

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).



451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# File 'lib/dommy/html_elements.rb', line 451

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.



531
532
533
# File 'lib/dommy/html_elements.rb', line 531

def select
  nil
end

#set_custom_validity(msg) ⇒ Object



588
589
590
591
# File 'lib/dommy/html_elements.rb', line 588

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

#set_range_text(_replacement, *_) ⇒ Object



539
540
541
# File 'lib/dommy/html_elements.rb', line 539

def set_range_text(_replacement, *_)
  nil
end

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



535
536
537
# File 'lib/dommy/html_elements.rb', line 535

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

#stepObject



393
394
395
# File 'lib/dommy/html_elements.rb', line 393

def step
  reflected_string("step")
end

#step_down(_n = 1) ⇒ Object



547
548
549
# File 'lib/dommy/html_elements.rb', line 547

def step_down(_n = 1)
  nil
end

#step_up(_n = 1) ⇒ Object



543
544
545
# File 'lib/dommy/html_elements.rb', line 543

def step_up(_n = 1)
  nil
end

#typeObject



360
361
362
363
# File 'lib/dommy/html_elements.rb', line 360

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

#type=(v) ⇒ Object



365
366
367
# File 'lib/dommy/html_elements.rb', line 365

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

#validation_messageObject



565
566
567
568
569
570
571
572
573
574
575
576
# File 'lib/dommy/html_elements.rb', line 565

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



551
552
553
# File 'lib/dommy/html_elements.rb', line 551

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.



425
426
427
# File 'lib/dommy/html_elements.rb', line 425

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

#value=(v) ⇒ Object



429
430
431
432
433
# File 'lib/dommy/html_elements.rb', line 429

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.



557
558
559
560
561
562
563
# File 'lib/dommy/html_elements.rb', line 557

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