Merge branch 'develop/UI-updates' into 'master'

Updates to form UI

See merge request cara/cara!94
This commit is contained in:
Philip James Elson 2020-11-17 21:32:50 +00:00
commit ae977b26d6
2 changed files with 116 additions and 80 deletions

View file

@ -1,25 +1,16 @@
function on_ventilation_type_change() {
ventilation_types = $('input[type=radio][name=ventilation_type]');
ventilation_types.each(function (index) {
if (this.checked) {
getChildElement($(this)).show();
require_fields(this);
} else {
getChildElement($(this)).hide();
unrequire_fields(this);
// Clear the inputs for this newly hidden child element.
getChildElement($(this)).find('input').not('input[type=radio]').val('');
getChildElement($(this)).find('input[type=radio]').prop("checked", false);
getChildElement($(this)).find('input').prop("required", false);
}
});
}
/* ------- HTML structure ------- */
function getChildElement(elem) {
// Get the element named in the given element's data-enables attribute.
return $("#" + elem.data("enables"));
}
function insertSpanAfter(referenceNode, text) {
var element = document.createElement("span");
element.classList.add("red_text");
element.innerHTML = "  " + text;
referenceNode.parentNode.insertBefore(element, referenceNode.nextSibling);
}
/* -------Required fields------- */
function require_fields(obj) {
switch ($(obj).attr('id')) {
@ -92,39 +83,47 @@ function unrequire_fields(obj) {
}
function require_room_volume(option) {
$("#room_volume").prop('required', option);
require_nonzero_field("room_volume", option);
}
function require_room_dimensions(option) {
$("#floor_area").prop('required', option);
$("#ceiling_height").prop('required', option);
require_nonzero_field("floor_area", option);
require_nonzero_field("ceiling_height", option);
}
function require_mechanical_ventilation(option) {
$("#air_type_changes").prop('required', option);
$("#air_type_supply").prop('required', option);
if (!option) {
removeInvalid("air_changes");
removeInvalid("air_supply");
}
}
function require_natural_ventilation(option) {
$("#windows_number").prop('required', option);
$("#window_height").prop('required', option);
$("#opening_distance").prop('required', option);
require_nonzero_field("windows_number", option);
require_nonzero_field("window_height", option);
require_nonzero_field("opening_distance", option);
$("#always").prop('required', option);
$("#interval").prop('required', option);
}
function require_air_changes(option) {
$("#air_changes").prop('required', option);
require_nonzero_field("air_changes", option);
}
function require_air_supply(option) {
$("#air_supply").prop('required', option);
require_nonzero_field("air_supply", option);
}
function require_single_event(option) {
$("#single_event_date").prop('required', option);
require_nonzero_field("single_event_date", option);
}
function require_nonzero_field(id, option) {
$("#"+id).prop('required', option);
if (!option)
removeInvalidDate();
removeInvalid(id);
}
function require_recurrent_event(option) {
@ -156,16 +155,14 @@ function require_mask(option) {
}
function require_hepa(option) {
$("#hepa_amount").prop('required', option);
require_nonzero_field("hepa_amount", option);
}
function setMaxInfectedPeople() {
$("#training_limit_error").hide();
var max = $("#total_people").val()
if ($("#activity_type").val() === "training")
{
if ($("#activity_type").val() === "training") {
max = 1;
$("#training_limit_error").show();
}
@ -173,6 +170,32 @@ function setMaxInfectedPeople() {
$("#infected_people").attr("max", max);
}
function removeInvalid(id) {
var obj = document.getElementById(id)
if (obj.classList.contains("red_border")) {
obj.value = "";
$(obj).removeClass("red_border");
$(obj).next('span').remove();
}
}
function on_ventilation_type_change() {
ventilation_types = $('input[type=radio][name=ventilation_type]');
ventilation_types.each(function (index) {
if (this.checked) {
getChildElement($(this)).show();
require_fields(this);
} else {
getChildElement($(this)).hide();
unrequire_fields(this);
// Clear the inputs for this newly hidden child element.
getChildElement($(this)).find('input').not('input[type=radio]').val('');
getChildElement($(this)).find('input[type=radio]').prop("checked", false);
getChildElement($(this)).find('input').prop("required", false);
}
});
}
/* -------UI------- */
$(function () {
$(".datepicker").datepicker({
@ -198,9 +221,14 @@ function show_disclaimer() {
/* -------Form validation------- */
function validate_form(form) {
var submit = true;
//Validate all non zero values
$("input[required].non_zero").each(function() {
if (!validateValue(this))
submit = false;
});
//Validate all dates
$("input[required].datepicker").each(function() {
if (!validateDate(this))
@ -216,28 +244,58 @@ function validate_form(form) {
return submit;
}
function validateDate(obj) {
function validateValue(obj) {
$(obj).removeClass("red_border");
$(obj).next().hide();
$(obj).next('span').remove();
var fromDate = $(obj).val();
if (!isValidDateOrEmpty(fromDate)) {
if (!isNonZeroOrEmpty($(obj).val())) {
$(obj).addClass("red_border");
$(obj).next().show();
insertSpanAfter(obj, "Value must be > 0");
return false;
}
return true;
}
function isNonZeroOrEmpty(value) {
if (value === "") return true;
if (value == 0)
return false;
return true;
}
function validateDate(obj) {
$(obj).removeClass("red_border");
$(obj).next('span').remove();
if (!isValidDateOrEmpty($(obj).val())) {
$(obj).addClass("red_border");
insertSpanAfter(obj, "Incorrect date format");
return false;
}
return true;
}
function isValidDateOrEmpty(date) {
if (date === "") return true;
var matches = /^(\d+)[-\/](\d+)[-\/](\d+)$/.exec(date);
if (matches == null) return false;
var d = matches[1];
var m = matches[2];
var y = matches[3];
if (y > 2100 || y < 1900) return false;
var composedDate = new Date(y + '/' + m + '/' + d);
return composedDate.getDate() == d && composedDate.getMonth() + 1 == m && composedDate.getFullYear() == y;
}
function validateFinishTime(obj) {
$(obj).removeClass("red_border");
$(obj).next().hide();
$(obj).next('span').remove();
var startTime = parseValToNumber($(obj).prev().val());
var finishTime = parseValToNumber(obj.value);
if (startTime > finishTime) {
$(obj).addClass("red_border");
$(obj).next().show();
insertSpanAfter(obj, "Finish time must be after start");
return false;
}
return true;
@ -256,30 +314,8 @@ function validateStartTime() {
}
}
function removeInvalidDate() {
var single_event_date = document.getElementById("single_event_date");
if (single_event_date.classList.contains("red_border"))
{
single_event_date.value = "";
$(single_event_date).next().hide();
$(single_event_date).removeClass("red_border");
}
}
function isValidDateOrEmpty(date) {
if (date === "") return true;
var matches = /^(\d+)[-\/](\d+)[-\/](\d+)$/.exec(date);
if (matches == null) return false;
var d = matches[1];
var m = matches[2];
var y = matches[3];
if (y > 2100 || y < 1900) return false;
var composedDate = new Date(y + '/' + m + '/' + d);
return composedDate.getDate() == d && composedDate.getMonth() + 1 == m && composedDate.getFullYear() == y;
}
function parseValToNumber(val) {
return parseInt(val.replace(':',''), 10);
return parseInt(val.replace(':',''), 10);
}
/* -------On Load------- */
@ -303,6 +339,10 @@ $(document).ready(function () {
$("#total_people").change(setMaxInfectedPeople);
$("#activity_type").change(setMaxInfectedPeople);
//Validate all non zero values
$("input[required].non_zero").each(function() {validateValue(this)});
$(".non_zero").change(function() {validateValue(this)});
//Validate all dates
$("input[required].datepicker").each(function() {validateDate(this)});
$(".datepicker").change(function() {validateDate(this)});

View file

@ -42,10 +42,10 @@
<span class="tooltip_text">?</span>
</div><br>
<input type="radio" id="room_type_volume" name="volume_type" value="room_volume" onclick="require_fields(this)" required>
Room volume: &nbsp;&nbsp; <input type="number" step=0.01 id="room_volume" name="room_volume" placeholder="Room volume (m³)" min="0.01"><br>
Room volume: &nbsp;&nbsp; <input type="number" step="any" id="room_volume" class="non_zero" name="room_volume" placeholder="Room volume (m³)" min="0"><br>
<input type="radio" id="room_type_dimensions" name="volume_type" value="room_dimensions" onclick="require_fields(this)" required>
Floor area: &nbsp;&nbsp; <input type="number" step=0.01 id="floor_area" name="floor_area" placeholder="Room floor area (m²)" min="0.01"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ceiling height: &nbsp;&nbsp; <input type="number" step=0.01 id="ceiling_height" name="ceiling_height" placeholder="Room ceiling height (m²)" min="0.01"><br>
Floor area: &nbsp;&nbsp; <input type="number" step="any" id="floor_area" class="non_zero" name="floor_area" placeholder="Room floor area (m²)" min="0"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ceiling height: &nbsp;&nbsp; <input type="number" step="any" id="ceiling_height" class="non_zero" name="ceiling_height" placeholder="Room ceiling height (m²)" min="0"><br>
<hr width="80%">
<!-- Ventilation Options -->
@ -60,15 +60,15 @@
<div id="DIVmechanical_ventilation" style="display:none">
<input type="radio" id="air_type_supply" name="mechanical_ventilation_type" value="air_supply" onclick="require_fields(this)">
Air supply flow rate &nbsp;&nbsp; <input type="number" step=0.01 id="air_supply" name="air_supply" min="0" placeholder="(m³ / hour)"><br>
Air supply flow rate &nbsp;&nbsp; <input type="number" step="any" id="air_supply" class="non_zero" name="air_supply" min="0" placeholder="(m³ / hour)"><br>
<input type="radio" id="air_type_changes" name="mechanical_ventilation_type" value="air_changes" onclick="require_fields(this)">
Air changes per hour &nbsp;&nbsp; <input type="number" step=0.01 id="air_changes" name="air_changes" min="0"><br>
Air changes per hour &nbsp;&nbsp; <input type="number" step="any" id="air_changes" class="non_zero" name="air_changes" min="0"><br>
</div>
<div id="DIVnatural_ventilation" style="display:none">
Number of windows: <input type="number" id="windows_number" name="windows_number" min="1"><br>
Height of window: <input type="number" step=0.01 id="window_height" name="window_height" placeholder="meters" min="0"><br>
Opening distance: <input type="number" step=0.01 id="opening_distance" name="opening_distance" placeholder="meters" min="0"><br>
Number of windows: <input type="number" id="windows_number" class="non_zero" name="windows_number" min="1"><br>
Height of window: <input type="number" step="any" id="window_height" class="non_zero" name="window_height" placeholder="meters" min="0"><br>
Opening distance: <input type="number" step="any" id="opening_distance" class="non_zero" name="opening_distance" placeholder="meters" min="0"><br>
Windows open: <input type="radio" id="always" name="windows_open" value="always">
<label for="always">Always</label>
<input type="radio" id="interval" name="windows_open" value="interval">
@ -81,7 +81,7 @@
<label for="hepa_no">No</label>
<input type="radio" id="hepa_yes" name="hepa_option" value=1 onclick="require_fields(this)">
<label for="hepa_yes">Yes</label>
<input type="number" step=0.01 id="hepa_amount" name="hepa_amount" placeholder="(m³ / hour)" min="0">
<input type="number" step="any" id="hepa_amount" class="non_zero" name="hepa_amount" placeholder="(m³ / hour)" min="0">
<hr width="80%">
<b>Face masks:</b>
@ -106,7 +106,7 @@
</div><br>
Total number of occupants: <input type="number" id="total_people" name="total_people" min=1 required><br>
Number of infected people: <input type="number" id="infected_people" name="infected_people" min=1 required><br>
<span id="training_limit_error" class="red_text" hidden>Training activities limited to 1 infected</span><br>
<span id="training_limit_error" class="red_text" hidden>Training activities limited to 1 infected<br></span>
<hr width="80%">
Activity type: <select id="activity_type" name="activity_type">
@ -119,12 +119,10 @@
<option value="gym">Gym</option>
</select><br>
Start: <input type="time" id="activity_start" class="start_time" name="activity_start" value="09:00" required> &nbsp;&nbsp;
Finish: <input type="time" id="activity_finish" class="finish_time" name="activity_finish" value="18:00" required>
<span id="activity_time_error" class="red_text" hidden>Finish time must be after start</span><br>
Finish: <input type="time" id="activity_finish" class="finish_time" name="activity_finish" value="18:00" required><br>
Infected person(s) presence: <br>
Start: <input type="time" id="infected_start" class="start_time" name="infected_start" value="09:00" required> &nbsp;&nbsp;
Finish: <input type="time" id="infected_finish" class="finish_time" name="infected_finish" value="18:00" required>
<span id="infected_time_error" class="red_text" hidden>Finish time must be after start</span><br>
Finish: <input type="time" id="infected_finish" class="finish_time" name="infected_finish" value="18:00" required><br>
<hr width="80%">
When is the event?
@ -135,8 +133,7 @@
<label for="event_type_single">Single event</label> &nbsp;&nbsp;
<label for="single_event_date">Date: </label>
<input type="text" id="single_event_date" class="datepicker" name="single_event_date" placeholder="dd/mm/yyyy">
<span id="event_time_error" class="red_text" hidden> Incorrect date format</span><br>
<input type="text" id="single_event_date" class="datepicker" name="single_event_date" placeholder="dd/mm/yyyy"><br>
<input type="radio" id="event_type_recurrent" name="event_type" value="recurrent_event" onclick="require_fields(this)" required>
<label for="event_type_recurrent">Recurrent usage</label>
<select id="recurrent_event_month" name="recurrent_event_month">
@ -165,8 +162,7 @@
<div id="DIVlunch_break">
Start: <input type="time" id="lunch_start" class="start_time" name="lunch_start" value="12:30" required> &nbsp;&nbsp;
Finish: <input type="time" id="lunch_finish" class="finish_time" name="lunch_finish" value="13:30" required>
<span id="lunch_time_error" class="red_text" hidden>Finish time must be after start</span><br>
Finish: <input type="time" id="lunch_finish" class="finish_time" name="lunch_finish" value="13:30" required><br>
</div>
<!-- Coffee Options -->