Class: Dommy::ValidityState

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

Overview

‘ValidityState` — computes constraint-validation flags from the host control’s current attributes and value. Bound to a single host control; reads dynamically on every access so attribute changes between calls are reflected.

Flags follow the HTML spec; ‘badInput` is always false (we’d need the browser’s number parser to detect “12abc” in a type=number).

Constant Summary collapse

FLAGS =
%w[
valueMissing
typeMismatch
patternMismatch
tooLong
tooShort
rangeUnderflow
rangeOverflow
stepMismatch
badInput
customError
    ]
.freeze
EMAIL_RE =
/\A[^@\s]+@[^@\s]+\.[^@\s]+\z/
URL_SCHEMES =
%w[http:// https:// ftp://].freeze

Instance Method Summary collapse

Constructor Details

#initialize(host = nil) ⇒ ValidityState

Returns a new instance of ValidityState.



685
686
687
# File 'lib/dommy/html_elements.rb', line 685

def initialize(host = nil)
  @host = host
end

Instance Method Details

#__js_get__(key) ⇒ Object

—- Bridge protocol —-



841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
# File 'lib/dommy/html_elements.rb', line 841

def __js_get__(key)
  case key
  when "valueMissing"
    value_missing
  when "typeMismatch"
    type_mismatch
  when "patternMismatch"
    pattern_mismatch
  when "tooLong"
    too_long
  when "tooShort"
    too_short
  when "rangeUnderflow"
    range_underflow
  when "rangeOverflow"
    range_overflow
  when "stepMismatch"
    step_mismatch
  when "badInput"
    bad_input
  when "customError"
    custom_error
  when "valid"
    valid
  end
end

#bad_inputObject

‘badInput` flags input that the user agent couldn’t convert to the host control’s expected type. For Dommy this is meaningful for type=number/range (raw string not a finite float) and type=color (not a #rrggbb literal).



798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
# File 'lib/dommy/html_elements.rb', line 798

def bad_input
  return false unless @host

  raw = @host.respond_to?(:raw_value) ? @host.raw_value : host_value
  raw = raw.to_s
  return false if raw.empty?

  case host_type
  when "number", "range"
    !valid_float?(raw)
  when "color"
    !raw.strip.downcase.match?(/\A#[0-9a-f]{6}\z/)
  else
    false
  end
end

#custom_errorObject



822
823
824
# File 'lib/dommy/html_elements.rb', line 822

def custom_error
  !custom_message.empty?
end

#pattern_mismatchObject



718
719
720
721
722
723
724
725
726
727
728
729
730
# File 'lib/dommy/html_elements.rb', line 718

def pattern_mismatch
  return false unless @host

  pat = host_attr_value("pattern").to_s
  return false if pat.empty?

  v = host_value.to_s
  return false if v.empty?

  !Regexp.new("\\A(?:#{pat})\\z").match?(v)
rescue RegexpError
  false
end

#range_overflowObject



767
768
769
770
771
772
773
774
775
# File 'lib/dommy/html_elements.rb', line 767

def range_overflow
  return false unless numeric_host?

  max = host_attr_value("max").to_s
  return false if max.empty?

  num = numeric_value
  num && num > max.to_f
end

#range_underflowObject



757
758
759
760
761
762
763
764
765
# File 'lib/dommy/html_elements.rb', line 757

def range_underflow
  return false unless numeric_host?

  min = host_attr_value("min").to_s
  return false if min.empty?

  num = numeric_value
  num && num < min.to_f
end

#step_mismatchObject



777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
# File 'lib/dommy/html_elements.rb', line 777

def step_mismatch
  return false unless numeric_host?

  step = host_attr_value("step").to_s
  return false if step.empty? || step == "any"

  step_n = step.to_f
  return false if step_n <= 0

  num = numeric_value
  return false unless num

  base = host_attr_value("min").to_s
  base_n = base.empty? ? 0.0 : base.to_f
  ((num - base_n) / step_n - ((num - base_n) / step_n).round).abs > 1e-9
end

#too_longObject



732
733
734
735
736
737
738
739
740
741
742
# File 'lib/dommy/html_elements.rb', line 732

def too_long
  return false unless @host

  max = host_attr_value("maxlength").to_s
  return false if max.empty?

  max_n = max.to_i
  return false if max_n < 0

  host_value.to_s.length > max_n
end

#too_shortObject



744
745
746
747
748
749
750
751
752
753
754
755
# File 'lib/dommy/html_elements.rb', line 744

def too_short
  return false unless @host

  min = host_attr_value("minlength").to_s
  return false if min.empty?

  min_n = min.to_i
  return false if min_n < 0

  v = host_value.to_s
  !v.empty? && v.length < min_n
end

#type_mismatchObject



702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
# File 'lib/dommy/html_elements.rb', line 702

def type_mismatch
  return false unless @host

  v = host_value.to_s
  return false if v.empty?

  case host_type
  when "email"
    !v.match?(EMAIL_RE)
  when "url"
    URL_SCHEMES.none? { |s| v.start_with?(s) }
  else
    false
  end
end

#validObject



826
827
828
829
830
831
832
833
834
835
836
837
# File 'lib/dommy/html_elements.rb', line 826

def valid
  !(value_missing ||
    type_mismatch ||
    pattern_mismatch ||
    too_long ||
    too_short ||
    range_underflow ||
    range_overflow ||
    step_mismatch ||
    bad_input ||
    custom_error)
end

#valid_float?(s) ⇒ Boolean

Returns:

  • (Boolean)


815
816
817
818
819
820
# File 'lib/dommy/html_elements.rb', line 815

def valid_float?(s)
  Float(s)
  true
rescue ArgumentError, TypeError
  false
end

#value_missingObject

—- Computed flags —-



691
692
693
694
695
696
697
698
699
700
# File 'lib/dommy/html_elements.rb', line 691

def value_missing
  return false unless @host && host_attr_present?("required")

  case host_type
  when "checkbox", "radio"
    !host_attr_present?("checked")
  else
    host_value.to_s.empty?
  end
end