diff --git a/cara/apps/calculator/static/js/form.js b/cara/apps/calculator/static/js/form.js index bc0612a9..f26cfa16 100644 --- a/cara/apps/calculator/static/js/form.js +++ b/cara/apps/calculator/static/js/form.js @@ -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)}); diff --git a/cara/apps/calculator/templates/calculator.form.html.j2 b/cara/apps/calculator/templates/calculator.form.html.j2 index a28fb5a8..91c90c4a 100644 --- a/cara/apps/calculator/templates/calculator.form.html.j2 +++ b/cara/apps/calculator/templates/calculator.form.html.j2 @@ -42,10 +42,10 @@ ?
- Room volume:   
+ Room volume:   
- Floor area:   
-       Ceiling height:   
+ Floor area:   
+       Ceiling height:   

@@ -60,15 +60,15 @@
Total number of occupants:
Number of infected people:
-
+
Activity type:
Start:    - Finish: -
+ Finish:
Infected person(s) presence:
Start:    - Finish: -
+ Finish:

When is the event? @@ -135,8 +133,7 @@    - -
+
   - Finish: -
+ Finish: