From 68d04d418f688ac59bd1f0284186132a6cce24e6 Mon Sep 17 00:00:00 2001 From: gb0101010101 <7369439+gb0101010101@users.noreply.github.com> Date: Wed, 6 May 2020 19:58:40 -0700 Subject: [PATCH] gb0101010101-decimal-quick-fix: Enforce form validation on AJAX submits. Create jinja2 macro to generate decimal form inputs, add custom JS validation for input type 'number' that uses attribute 'pattern' which is not natively supported in HTML5. --- static/scripts/frontpage3d.js | 21 +++++++++++++ static/scripts/frontpage3dcontrols.js | 8 +++++ static/scripts/frontpageControls.js | 32 ++++++++++++++----- static/scripts/settings.js | 7 ++++- templates/editBoard.html | 12 +++---- templates/editBoard_mobile.html | 12 +++---- templates/frontpage3d.html | 6 ++-- templates/frontpage3d_mobile.html | 4 +-- templates/frontpage3d_mobilecontrols.html | 4 +-- templates/holeyCalibration.html | 26 ++++++++-------- templates/macros.html | 5 +++ templates/opticalCalibration.html | 38 ++++++++++++----------- templates/pidTuning.html | 32 +++++++++---------- templates/quickConfigure.html | 7 +++-- templates/settings.html | 2 +- templates/settings_mobile.html | 2 +- templates/triangularCalibration.html | 10 +++--- templates/trimBoard.html | 10 +++--- templates/zaxis.html | 4 +-- templates/zaxis_mobile.html | 4 +-- 20 files changed, 153 insertions(+), 93 deletions(-) create mode 100644 templates/macros.html diff --git a/static/scripts/frontpage3d.js b/static/scripts/frontpage3d.js index 7491e3e8..1a625682 100644 --- a/static/scripts/frontpage3d.js +++ b/static/scripts/frontpage3d.js @@ -807,3 +807,24 @@ function toggle3DPO(){ } } +function onFooterSubmit(){ + var form = $("#settingsForm") + // JQuery returns list of forms so must select first [0]. + isValid = form[0].checkValidity(); + if (isValid) { + var url = $("#pageID").val() + $.ajax({ + url : '/'+url, + type: "POST", + data: form.serialize(), + success: function (data) { + console.log("success"); + $('#contentModal').modal('toggle') + }, + error: function (jXHR, textStatus, errorThrown) { + alert(errorThrown); + } + }); + } +} + diff --git a/static/scripts/frontpage3dcontrols.js b/static/scripts/frontpage3dcontrols.js index d55cf71b..fb2560f8 100644 --- a/static/scripts/frontpage3dcontrols.js +++ b/static/scripts/frontpage3dcontrols.js @@ -152,3 +152,11 @@ function processStatusMessage(data){ else $("#currentPositioningMode").text("Incremental (G91)"); } + +function inputDecimalValidate() { + var re = new RegExp($(this).attr("pattern")); + valid = pattern.test($(this).val()); + if (!valid) { + $(this).setCustomValidity("Decimal input pattern mismatch"); + } +} diff --git a/static/scripts/frontpageControls.js b/static/scripts/frontpageControls.js index dc0bb784..42aeb37f 100644 --- a/static/scripts/frontpageControls.js +++ b/static/scripts/frontpageControls.js @@ -22,6 +22,25 @@ $(document).ready(function(){ var controllerMessage = document.getElementById('controllerMessage'); controllerMessage.scrollTop = controllerMessage.scrollHeight; $("#stickyButtons").css("top", $(".navbar").outerHeight()); + + // Set custom validation on all form inputs of type 'number' with attribute 'pattern'. + // Input type 'number' does not support 'pattern' attribute by default using HTML5. + // Input type 'number' always returns a value compatible with parseFloat using period as decimal separator. + // @todo: This event handler may need to be moved to other JS files for more/less global application. + $(':input[type="number"][pattern]').change(function () { + var re = new RegExp($(this).attr("pattern")); + var isValid = re.test($(this).val()); + // JQuery selector returns array of possible matches. + // Validity checks must be applied to first item [0]. + if (isValid) { + // Set empty value to clear error. + $(this)[0].setCustomValidity(""); + } + else { + // Set title as error message. + $(this)[0].setCustomValidity($(this).attr("title")); + } + }); }); function pauseRun(){ @@ -138,13 +157,12 @@ function boardDataUpdate(data){ } function moveAction(direction) { - distance = $("#distToMove").val(); - distanceValid = distance.search(/^[0-9]*(\.[0-9]{0,3})?$/); - if (distanceValid == 0) { - action('move', direction, distance); - } else { - $("#distToMove").focus(); - } + // JQuery returns list of matching forms so select first [0] for validitity checking. + var isValid = $("#distInput")[0].checkValidity(); + if (isValid) { + distance = $("#distToMove").val(); + action('move', direction, distance); + } } function processStatusMessage(data){ diff --git a/static/scripts/settings.js b/static/scripts/settings.js index ea7a5472..45271612 100644 --- a/static/scripts/settings.js +++ b/static/scripts/settings.js @@ -1,9 +1,11 @@ function onFooterSubmit(){ + var form = $("#settingsForm") + if (form[0].checkValidity()) { var url = $("#pageID").val() $.ajax({ url : '/'+url, type: "POST", - data: $("#settingsForm").serialize(), + data: form.serialize(), success: function (data) { console.log("success"); $('#contentModal').modal('toggle') @@ -12,8 +14,10 @@ function onFooterSubmit(){ alert(errorThrown); } }); + } } +/* $(document).ready(function () { $('#settingsForm').on('submit', function(e) { e.preventDefault(); @@ -38,6 +42,7 @@ $(document).ready(function () { }); }); +*/ function updatePorts(data){ var selectedPort = $("#comPorts").find(":selected").text(); diff --git a/templates/editBoard.html b/templates/editBoard.html index d0faf3c2..b0ab1c09 100644 --- a/templates/editBoard.html +++ b/templates/editBoard.html @@ -1,4 +1,4 @@ - +{% import 'macros.html' as macros %} {% block content %}
@@ -32,17 +32,17 @@

- + {{ macros.input_decimal("width", False, width) }} Enter value in {{units}} only
- + {{ macros.input_decimal("height", True, height) }} Enter value in {{units}} only
- + {{ macros.input_decimal("thickness", True, thickness) }} Enter value in {{units}} only
@@ -56,12 +56,12 @@

- + {{ macros.input_decimal("centerX", True, centerX) }} Enter value in {{units}} only
- + {{ macros.input_decimal("centerY", True, centerY) }} Enter value in {{units}} only
diff --git a/templates/editBoard_mobile.html b/templates/editBoard_mobile.html index add13a10..8f562600 100644 --- a/templates/editBoard_mobile.html +++ b/templates/editBoard_mobile.html @@ -1,4 +1,4 @@ - +{% import 'macros.html' as macros %} {% block content %}
@@ -28,17 +28,17 @@

- + {{ macros.input_decimal("width", True, width) }} Enter value in {{units}} only
- + {{ macros.input_decimal("height", True, height) }} Enter value in {{units}} only
- + {{ macros.input_decimal("thickness", True, thickness) }} Enter value in {{units}} only
@@ -50,12 +50,12 @@

- + {{ macros.input_decimal("centerX", True, centerX) }} Enter value in {{units}} only
- + {{ macros.input_decimal("centerY", True, centerY) }} Enter value in {{units}} only
diff --git a/templates/frontpage3d.html b/templates/frontpage3d.html index a902f1c6..926cdeb9 100644 --- a/templates/frontpage3d.html +++ b/templates/frontpage3d.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} - +{% import 'macros.html' as macros %} {% block header %} @@ -26,7 +26,7 @@

Controls

- +
@@ -68,7 +68,7 @@

Controls

- +
{{ macros.input_decimal("distToMove", True) }}
diff --git a/templates/frontpage3d_mobile.html b/templates/frontpage3d_mobile.html index d4091665..dd818acf 100644 --- a/templates/frontpage3d_mobile.html +++ b/templates/frontpage3d_mobile.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} - +{% import 'macros.html' as macros %} {% block header %} @@ -83,7 +83,7 @@

Controls

-
+
{{ macros.input_decimal("distToMove", True) }}
diff --git a/templates/frontpage3d_mobilecontrols.html b/templates/frontpage3d_mobilecontrols.html index 2aeb7354..cf318c7e 100644 --- a/templates/frontpage3d_mobilecontrols.html +++ b/templates/frontpage3d_mobilecontrols.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} - +{% import 'macros.html' as macros %} {% block header %} @@ -86,7 +86,7 @@

Controls

- +
{{ macros.input_decimal("distToMove", True) }}
diff --git a/templates/holeyCalibration.html b/templates/holeyCalibration.html index 2a011918..c07e38b3 100644 --- a/templates/holeyCalibration.html +++ b/templates/holeyCalibration.html @@ -1,4 +1,4 @@ - +{% import 'macros.html' as macros %} {% block content %}
@@ -14,62 +14,62 @@

Measurements

- + {{ macros.input_decimal("M1", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M2", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M3", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M4", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M5", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M6", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M7", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M8", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M9", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M10", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M11", True, "0") }} Enter value in mm only
- + {{ macros.input_decimal("M12", True, "0") }} Enter value in mm only
diff --git a/templates/macros.html b/templates/macros.html new file mode 100644 index 00000000..87a2afce --- /dev/null +++ b/templates/macros.html @@ -0,0 +1,5 @@ +{% macro input_decimal(id, required = False, default_value = "", disabled = False, digits_before = 4, digits_after = 5, error_text = "") %} + {% set pattern = "^[0-9]{0," ~ digits_before ~ "}([\.,][0-9]{0," ~ digits_after ~ "})?$" %} + {% set title = error_text|default("Decimal number with one separator with max " ~ digits_before ~ " major digits and max " ~ digits_after + " minor digits", True) %} + +{% endmacro %} \ No newline at end of file diff --git a/templates/opticalCalibration.html b/templates/opticalCalibration.html index 5874b48c..6d74b471 100644 --- a/templates/opticalCalibration.html +++ b/templates/opticalCalibration.html @@ -1,4 +1,4 @@ - +{% import 'macros.html' as macros %} {% block content %}
@@ -16,14 +16,14 @@

- + {{ macros.input_decimal("markerX", True, markerX) }} Enter value in inches only
- + {{ macros.input_decimal("markerY", True, markerY) }} Enter value in inches only
@@ -32,13 +32,14 @@

- + {{ macros.input_decimal("scaleX", True, scaleX) }} Enter something like 1.0028
+ {{ macros.input_decimal("scaleY", True, scaleY) }} Enter something like 1.0028
@@ -48,14 +49,14 @@

- + {{ macros.input_decimal("opticalCenterX", True, opticalCenterX) }} Enter something like 300
- + {{ macros.input_decimal("opticalCenterY", True, opticalCenterY) }} Enter something like 200
@@ -64,7 +65,7 @@

- + {{ macros.input_decimal("positionTolerance", True, positionTolerance) }} Enter something like 0.125 (mm)
@@ -91,17 +92,18 @@

Calibration Extents

+ {% set disabled_custom = (calibrationExtents!='Custom') %}
- + {{ macros.input_decimal("tlX", True, tlX, disabled_custom) }} Range from +15 to -15 (+ is right, - is left)
- + {{ macros.input_decimal("tlY", True, tlY, disabled_custom) }} Range from +7 to -7 (+ is up, - is down)
@@ -110,14 +112,14 @@

Calibration Extents

- + {{ macros.input_decimal("brX", True, brX, disabled_custom) }} Range from +15 to -15 (+ is right, - is left)
- + {{ macros.input_decimal("brY", True, brY, disabled_custom) }} Range from +7 to -7 (+ is up, - is down)
@@ -156,14 +158,14 @@

- + {{ macros.input_decimal("markerX", True, markerX) }} Enter value in inches only
- + {{ macros.input_decimal("markerY", True, markerY) }} Enter value in inches only
@@ -172,14 +174,14 @@

- + {{ macros.input_decimal("scaleX", True, scaleX) }} Enter something like 1.0028
- + {{ macros.input_decimal("scaleY", True, scaleY) }} Enter something like 1.0028
@@ -188,14 +190,14 @@

- + {{ macros.input_decimal("opticalCenterY", True, opticalCenterY) }} Enter something like 300
- + {{ macros.input_decimal("opticalCenterY", True, opticalCenterY) }} Enter something like 200
@@ -204,7 +206,7 @@

- + {{ macros.input_decimal("positionTolerance", True, positionTolerance) }} Enter something like 0.125 (mm)
diff --git a/templates/pidTuning.html b/templates/pidTuning.html index 3b50622c..500c5555 100644 --- a/templates/pidTuning.html +++ b/templates/pidTuning.html @@ -1,4 +1,4 @@ - +{% import 'macros.html' as macros %} {% block content %}
@@ -290,14 +290,14 @@

Settings

- + {{ macros.input_decimal("vStart", False, vStart) }}
- + {{ macros.input_decimal("vStop", False, vStop) }}
@@ -306,14 +306,14 @@

Settings

- + {{ macros.input_decimal("vSteps", False, vSteps) }}
- + {{ macros.input_decimal("vVersion", False, vVersion) }}
@@ -322,21 +322,21 @@

Settings

- + {{ macros.input_decimal("KpV", False, KpV) }}
- + {{ macros.input_decimal("KiV", False, KiV) }}
- + {{ macros.input_decimal("KdV", False, KdV) }}
@@ -393,14 +393,14 @@

Settings

- + {{ macros.input_decimal("pStart", False, pStart) }}
- + {{ macros.input_decimal("pStop", False, pStop) }}
@@ -409,14 +409,14 @@

Settings

- + {{ macros.input_decimal("pSteps", False, pSteps) }}
- + {{ macros.input_decimal("pVersion", False, pVersion) }}
@@ -425,7 +425,7 @@

Settings

- + {{ macros.input_decimal("pTime", False, pTime) }}
@@ -434,21 +434,21 @@

Settings

- + {{ macros.input_decimal("KpP", False, KpP) }}
- + {{ macros.input_decimal("KiP", False, KiP) }}
- + {{ macros.input_decimal("KdV", False, KdV) }}
diff --git a/templates/quickConfigure.html b/templates/quickConfigure.html index 278a4e72..8c953578 100644 --- a/templates/quickConfigure.html +++ b/templates/quickConfigure.html @@ -1,3 +1,4 @@ +{% import 'macros.html' as macros %} {% block content %}
@@ -48,7 +49,7 @@
Metal Maslow Linkage

- + {{ macros.input_decimal("rotationRadius", False, rotationRadius) }} Enter value in mm only
@@ -80,7 +81,7 @@

Distance Between Motors

- + {{ macros.input_decimal("motorSpacingX", False, motorSpacingX) }} Enter value in mm only
@@ -95,7 +96,7 @@

Height of Motors Above Workspace

- + {{ macros.input_decimal("motorOffsetY", False, motorOffsetY) }} Enter value in mm only
diff --git a/templates/settings.html b/templates/settings.html index 94cd7639..ea2654f5 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -46,7 +46,7 @@

{{sett {% else %} - + {% endif %}

diff --git a/templates/settings_mobile.html b/templates/settings_mobile.html index a10e22a2..9635f5ff 100644 --- a/templates/settings_mobile.html +++ b/templates/settings_mobile.html @@ -46,7 +46,7 @@

{{sett {% else %} - + {% endif %}

diff --git a/templates/triangularCalibration.html b/templates/triangularCalibration.html index 1a3a0f49..64fe4650 100644 --- a/templates/triangularCalibration.html +++ b/templates/triangularCalibration.html @@ -1,4 +1,4 @@ - +{% import 'macros.html' as macros %} {% block content %}
Cut Test Pattern
@@ -11,22 +11,22 @@
Measurements
- + {{ macros.input_decimal("cut12", True, "1930") }} Enter value in mm only
- + {{ macros.input_decimal("cut34", True, "1930") }} Enter value in mm only
- + {{ macros.input_decimal("cut5", True, "300") }} Enter value in mm only
- + {{ macros.input_decimal("bitDiameter", True, "6.35") }} Enter value in mm only
diff --git a/templates/trimBoard.html b/templates/trimBoard.html index ac8257ad..a20fe9a5 100644 --- a/templates/trimBoard.html +++ b/templates/trimBoard.html @@ -1,4 +1,4 @@ - +{% import 'macros.html' as macros %} {% block content %}
@@ -7,26 +7,26 @@
- + {{ macros.input_decimal("trimTop", True, "0") }} Enter value in {{units}} only
- + {{ macros.input_decimal("trimLeft", True, "0") }} Enter value in {{units}} only
- + {{ macros.input_decimal("trimRight", True, "0") }} Enter value in {{units}} only
- + {{ macros.input_decimal("trimBottom", True, "0") }} Enter value in {{units}} only
diff --git a/templates/zaxis.html b/templates/zaxis.html index 024e8c45..1e087d6c 100644 --- a/templates/zaxis.html +++ b/templates/zaxis.html @@ -1,11 +1,11 @@ - +{% import 'macros.html' as macros %} {% block content %}
- + {{ macros.input_decimal("distToMoveZ", True, distToMoveZ) }}
diff --git a/templates/zaxis_mobile.html b/templates/zaxis_mobile.html index a22c2179..84dfef7d 100644 --- a/templates/zaxis_mobile.html +++ b/templates/zaxis_mobile.html @@ -1,11 +1,11 @@ - +{% import 'macros.html' as macros %} {% block content %}
- + {{ macros.input_decimal("distToMoveZ", True, distToMoveZ) }}