#javascript #html #jquery
#javascript #HTML #jquery
Вопрос:
Как вы видите в коде, я хочу, чтобы пользователи могли выбирать время между открытием и закрытием (мин.макс), но оно не работает, это займет все введенное время, а иногда оно будет работать только в течение максимального времени. Я видел похожие вопросы, я не мог найти никаких решений.
часть кода —
temple_name| temple_opentime | temple_closetime
-----------------------------------------------
temple1 | 9:30 | 18:30 |
temple2 | 7:30 | 21:00 |
temple3 | 10:00 | 18:00 |
temple4 | 8:30 | 20:00 |
<select id="temple" class="form-control">
<?php
require "config/database.php";
$sql = "select * from entity_temple";
$result = mysqli_query($link, $sql);
while($row = mysqli_fetch_array($result))
{
echo '<option name="'.$row["temple_opentime"].'" data-value="'. $row["temple_closetime"].'" value="'. $row["temple_name"].'">'. $row["temple_name"].'</option>';
}
?>
</select>
<div class="form-group col-md-4">
<label for="time" class="form-label">Time:</label>
<input type="time" id="time" name="time" min="" max="" step="600" class="form-control">
</div>
<div class="form-group d-grid col-4 mx-auto">
<button type="submit" name="save" class="btn btn-block btn-outline-dark" id="butsave">Add Request</button>
</div>
$("#temple").on("change", function () {
var value = $('#temple').val();
var nm = $('#temple option[value="' value '"]').attr('name');
var dv = $('#temple [value="' value '"]').data('value');
$("#time").attr({
"max" : dv,
"min" : nm
});
Комментарии:
1. Добро пожаловать в Stack Overflow. Из моего примера неясно, что вы пробовали. Я вижу, что он собирает Min и Max, тогда что вы хотели, чтобы он делал?
2. да, он даже правильно устанавливает min и max, но он не будет работать по назначению, также потребуется время, введенное за пределами min и max
3. Вы проверили поддержку браузером ввода type=»time» ?
4. да, теперь это работает, кто-то только что ответил на него (и удалил ответ), просто нужно было добавить 0 перед 9:30 , 7:30 , 8:30 как 09:30, 07:30, 08:30,
Ответ №1:
Я бы использовал атрибуты данных для времени открытия и закрытия… И с осмысленными именами. 😉
Ваш SQL должен быть:
while($row = mysqli_fetch_array($result)){
echo '<option value="'.$row["temple_name"].'" data-opentime="'. $row["temple_opentime"].'" data-closetime="'. $row["temple_closetime"].'">'. $row["temple_name"].'</option>';
}
Я заметил, что время НЕ отображается во входных данных, если значение не имеет начального нуля… Так 7:30
что не работает, но 07:30
работает.
Теперь об атрибутах min
и max
для ввода времени …
Пока нет проверки, сделанной из коробки браузером…
Вы можете заметить, что даже пример MDN ведет себя не так, как должен.
Итак, я добавил что-то вроде базового средства проверки. Это, по крайней мере, предотвращает отправку формы и добавляет класс к элементу time, если выбранное значение неверно.
$("#temple").on("change", function() {
var value = $('#temple').val();
var min = $('#temple option[value="' value '"]').data('opentime');
var max = $('#temple [value="' value '"]').data('closetime');
console.log(value, min, max)
$("#time").attr({
value: min,
max,
min
});
});
$("#timeForm").on("submit", function(e){
e.preventDefault();
let time = $("#time");
if( time.val() < time.attr("min") || time.val() > time.attr("max") ){
time.addClass("error");
return;
}
// if the time is correct, submit
$(this).submit();
});
$("#timeForm").on("change",function(){
$("#time").removeClass("error");
});
.error{
background: red;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<form id="timeForm">
<select id="temple" class="form-control">
<option disabled selected>Select a temple</option>
<option value="temple1" data-opentime="09:30" data-closetime="18H30">temple1</option>
<option value="temple2" data-opentime="07:30" data-closetime="21:00">temple2</option>
<option value="temple3" data-opentime="10:00" data-closetime="18:00">temple3</option>
<option value="temple4" data-opentime="08:30" data-closetime="20:00">temple4</option>
</select>
<div class="form-group col-md-4">
<label for="time" class="form-label">Time:</label>
<input type="time" id="time" name="time" min="" max="" step="600" class="form-control" required>
</div>
<div class="form-group d-grid col-4 mx-auto">
<button type="submit" name="save" class="btn btn-block btn-outline-dark" id="butsave">Add Request</button>
</div>
</form>
Ответ №2:
Рассмотрим следующее.
$(function() {
$("#temple").on("change", function() {
var item = $(":selected", this),
op = item.data("open-time"),
cl = item.data("close-time");
$("#time").attr({
min: op,
max: cl,
value: op
}).trigger("input");
});
$("#time").on("change", function(e) {
if ($(this).val() < $(this).attr("min")) {
$(this).val($(this).attr("min"));
} else if ($(this).val() > $(this).attr("max")) {
$(this).val($(this).attr("min"));
}
});
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3 Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--
temple_name| temple_opentime | temple_closetime
-----------------------------------------------
temple1 | 9:30 | 18:30 |
temple2 | 7:30 | 21:00 |
temple3 | 10:00 | 18:00 |
temple4 | 8:30 | 20:00 |
-->
<select id="temple" class="form-control">
<option>---</option>
<option data-open-time="09:30" data-close-time="18:30" value="Temple1">Temple1</option>
<option data-open-time="07:30" data-close-time="21:00" value="Temple2">Temple2</option>
<option data-open-time="10:00" ddata-close-time="18:00" value="Temple3">Temple3</option>
<option data-open-time="08:30" data-close-time="20:00" value="Temple1">Temple4</option>
</select>
<div class="form-group col-md-4">
<label for="time" class="form-label">Time:</label>
<input type="time" id="time" name="time" min="" max="" step="600" class="form-control" required>
</div>
<div class="form-group d-grid col-4 mx-auto">
<button type="submit" name="save" class="btn btn-block btn-outline-dark" id="butsave">Add Request</button>
</div>
Здесь, когда выбран параметр, обновляются Минимальные, Максимальные и значения введенного времени. после обновления мы запускаем событие ввода, это приведет к тому, что Значение появится у пользователя. Во входных данных могут быть значения, которые находятся за пределами значений Min и Max, это приведет к тому, что входные данные будут недопустимыми. Если пользователь затем отрегулирует время, оно будет вынуждено соответствовать Минимальному максимуму с помощью jQuery.
Смотрите больше: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time#Time_value_format
Примечание: Когда данные, введенные пользователем, не соответствуют пошаговой конфигурации, агент пользователя может округлить до ближайшего допустимого значения, предпочитая числа в положительном направлении, когда есть два одинаково близких варианта.
Это свойство имеет некоторые странные эффекты в разных браузерах, поэтому не является полностью надежным.
Ответ №3:
Как указывалось выше, проблема с операционным кодом была просто опечаткой:
Входные min
данные и max
значения атрибутов должны быть строками в форме «hh: mm» («h: mm» недопустимо).:
<input type="time" min="08:30" max="16:00">
Однако это исправление опечатки само по себе не устраняет несовместимость с браузером. Как утверждает MDN:
… в Safari и любых других браузерах, которые не поддерживают
<time>
, он [<input type="time">
] изящно деградирует до<input type="text">
.
и degraded input
не будет проверяться на наличие ошибок min / max.
Чтобы устранить эту несовместимость с браузером, приведенный ниже код обнаруживает входные данные, которые были преобразованы в форму <input type="text" min="hh:mm" max="hh:mm">
, и добавляет в форму скрипт проверки.
Если обнаружена ошибка проверки, сообщение об ошибке будет показано в виде наложения над входными данными (соответствует собственному поведению в Chrome и Firefox).
// the "real" form submits
const timeForm = document.getElementById('formtime');
timeForm.onsubmit = function () {
alert('time form was submitted');
};
const textForm = document.getElementById('formtext');
textForm.onsubmit = function () {
alert('text form was submitted');
};
// time validator for degraded time inputs
// Note: This must be loaded AFTER all user form submitters have
// been added
(function () {
// error overlay custom element
class ErrorOverlay extends HTMLElement {
constructor () {
super();
// create a shadow root
let shadowRoot = this.attachShadow({mode: 'open'});
// create shadow DOM element
const overlay = document.createElement('div');
this.overlay = overlay;
overlay.className = 'error-overlay';
// create css for the shadow DOM
const style = document.createElement('style');
style.textContent = `
.error-overlay {
font-family: Helvetica, sans-serif;
position: absolute;
z-index: 1000;
border: 1px solid #808080;
border-radius: 4px;
color: #f8f8f8;
background-color: #808080;
padding: 0.2rem 0.4rem;
display: none;
}
.error-overlay::after {
content: " ";
position: absolute;
top: 100%;
left: 24px;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #808080 transparent transparent transparent;
}
`;
// attach shadow DOM to shadow root
shadowRoot.appendChild(style);
shadowRoot.appendChild(overlay);
}
// show error overlay above the input
show (input, message) {
const {top, right, bottom, left} = input.getBoundingClientRect();
const overlay = this.overlay;
overlay.style.top = Math.round(top - 34 window.scrollY) 'px';
overlay.style.left = Math.round(left) 'px';
overlay.innerText = message;
overlay.style.display = 'block';
// hide overlay
function overlayHide () {
overlay.style.display = 'none';
// remove listeners
input.removeEventListener('keyup', overlayHide);
input.removeEventListener('blur', overlayHide);
}
// add input listeners and focus the input
input.addEventListener('keyup', overlayHide);
input.addEventListener('blur', overlayHide);
input.focus();
}
}
// create overlay instance amp; add to body
customElements.define('error-overlay', ErrorOverlay);
const errorOverlay = document.createElement('error-overlay');
document.body.appendChild(errorOverlay);
// convert time string to decimal hours
// time string patterns: "hh:mm AM", "hh:mm PM", "hh:mm"
function timeStringToDecimalHours (timeStr) {
let [hhmm, ampm] = timeStr.split(' ');
ampm = (ampm || '').toLowerCase();
let [hour, minute] = hhmm.split(':').map(el => Number(el));
if (ampm === 'pm' amp;amp; hour < 12) {
hour = 12;
} else if (ampm === 'am' amp;amp; hour === 12) {
hour = 0;
}
return hour (minute / 60);
}
// get array of inputs that have this pattern:
// <input type="text" min="hh:mm" max="hh:mm">
function getDegradedTimeInputs (form) {
return Array.from(form.querySelectorAll('input'))
.filter(input => {
if (input.type !== 'text') { return false; }
return input.hasAttribute('min') ||
input.hasAttribute('max');
});
}
// validate inputs when form is submitted
function validateTimeOnFormSubmit (evt) {
// get form's inputs that have type="text", `min` and/or `max`
const form = evt.target;
const tInputs = getDegradedTimeInputs(form);
// validate that each input value is between min and max
for (const input of tInputs) {
const {value, max, min} = input;
// convert time strings into decimal hours
const valTime = timeStringToDecimalHours(value),
minTime = timeStringToDecimalHours(min),
maxTime = timeStringToDecimalHours(max);
if (valTime < minTime || maxTime < valTime) {
// show the error overlay and prevent the submit
errorOverlay.show(input, `Time must be between ${min} and ${max}`);
return false;
}
}
// complete the submit
return form.realOnSubmit(evt);
}
// add time validator to all forms that contain degraded time inputs
const forms = document.querySelectorAll('form');
function submitHandlerStub () { return true; }
for (const form of forms) {
if (getDegradedTimeInputs(form).length > 0) {
// store the real submit handler as `form.realOnSubmit`
const realOnSubmit = form.onsubmit || submitHandlerStub;
Object.defineProperty(form, 'realOnSubmit', {
value: realOnSubmit,
enumerable: false
});
form.onsubmit = validateTimeOnFormSubmit;
}
}
})();
form {
border: 1px solid black;
max-width: 30rem;
margin: 1rem 0;
padding: 0.5rem;
}
<h1>Validate a form's degraded time inputs</h1>
<p>Some browsers do not support <code>amp;<input type="time"></code>, degrading it to <code>amp;<input type="text"></code>.</p>
<p>This script detects these degraded inputs and validates them accordingly.</p>
<form id="formtime">
<label for="timeinput">TIME input (min 09:30, max: 14:00):</label>
<input id="timeinput" type="time" min="09:30" max="14:00" placeholder="hh:mm AM/PM" />
<button type="submit">Submit</button>
</form>
<form id="formtext">
<label for="degraded">TEXT input (min 09:30, max: 14:00):</label>
<input id="degraded" type="text" min="09:30" max="14:00" style="width: 5rem" placeholder="hh:mm AM/PM" />
<button type="submit">Submit</button>
</form>