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.



1201
1202
1203
# File 'lib/dommy/html_elements.rb', line 1201

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

Instance Method Details

#__js_get__(key) ⇒ Object

—- Bridge protocol —-



1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
# File 'lib/dommy/html_elements.rb', line 1357

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



1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
# File 'lib/dommy/html_elements.rb', line 1314

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



1338
1339
1340
# File 'lib/dommy/html_elements.rb', line 1338

def custom_error
  !custom_message.empty?
end

#pattern_mismatchObject



1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
# File 'lib/dommy/html_elements.rb', line 1234

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



1283
1284
1285
1286
1287
1288
1289
1290
1291
# File 'lib/dommy/html_elements.rb', line 1283

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



1273
1274
1275
1276
1277
1278
1279
1280
1281
# File 'lib/dommy/html_elements.rb', line 1273

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



1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
# File 'lib/dommy/html_elements.rb', line 1293

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



1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
# File 'lib/dommy/html_elements.rb', line 1248

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



1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
# File 'lib/dommy/html_elements.rb', line 1260

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



1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
# File 'lib/dommy/html_elements.rb', line 1218

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



1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
# File 'lib/dommy/html_elements.rb', line 1342

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)


1331
1332
1333
1334
1335
1336
# File 'lib/dommy/html_elements.rb', line 1331

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

#value_missingObject

—- Computed flags —-



1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
# File 'lib/dommy/html_elements.rb', line 1207

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