Can anyone bring some light in this issue:
I created a basic webapp form with Google Apps Scripts to scan Qr codes (library https://unpkg.com/html5-qrcode
) and send the data to Google Sheet. It will be used on mobile phones. I wanted to use Materialize, so I used the relevant library for this purpose from here:
<!-- Compiled and minified CSS --> and <!-- Compiled and minified JavaScript -->
The issue is that when scanning, sometimes the camera faces back (desired behavior) and sometimes faces front. It has an inconsistent behavior in terms of which camera (front/back) will start. Also, I cannot select the camera (front or back)
So I tried few things to force the back camera, for example:
qrReader = new Html5QrcodeScanner("qr-reader", { fps: 10, qrbox: 250, facingMode: 'environment' });
, but it didn't work.
I tried other suggested methods (e.g. Html5Qrcode.getCameras().then(devices => { ...
etc ), but no success.
Until I realised that when removing this line below only, I can select the camera I want to use:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
As soon I remove the Compiled and minified CSS I can see the dropdown menu to select any camera I want to use:
Question
Is there a solution to this conflict without loosing the Materialize styles?
Whole code:
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Bree+Serif|Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i&display=swap&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script src="https://unpkg.com/html5-qrcode"></script>
<style>
/* Add the styles for the QR code scanner */
#qr-reader {
width: 70%; /* Reduced QR code scanner size */
max-width: 100%;
height: 70%;
margin: 10px auto; /* Space between buttons and QR code scanner */
}
/* Larger text size for labels */
.switch label {
font-size: 24px !important;
}
/* Increase the switch size */
.switch label .lever {
width: 30px; /* Adjust the width to make the switch larger */
}
/* Adjust the switch's margin for better alignment */
.switch label {
margin: 0;
}
#responseMessage {
font-size: 18px;
}
.large-text {
font-size: 18px; /* Adjust the font size as needed */
}
.counter-wrapper {
display: flex;
justify-content: center;
}
.counter-container {
display: flex;
justify-content: center;
}
.counter-box {
text-align: center;
border: 1px solid #2196F3;
border-radius: 10px;
}
.counter-box h6 {
font-size: 14px;
color: #2196F3;
margin: 0px; /* Adjust the margin */
}
.counter-box p {
font-size: 18px;
color: #ee0979;
margin: 0px; /* Adjust the margin */
}
</style>
</head>
<body>
<!-- Logo and Title -->
<div class="row center">
<img src="https://www.mtp.es/wp-content/uploads/2019/03/testing-1200x900.jpg" alt="Logo" class="responsive-img"
style="width: 200px;">
<h5>Attendance</h5>
</div>
<div class="row center counter-container">
<div class="col s6"> <!-- Create a column for "Total Present" -->
<div class="counter-wrapper">
<div class="counter-box" style="width: 450px;"> <!-- Increase width to 250px -->
<h6>Total Present</h6>
<p id="presentCount" class="counter">0</p>
</div>
</div>
</div>
<div class="col s6"> <!-- Create a column for "Total Absent" -->
<div class="counter-wrapper">
<div class="counter-box" style="width: 450px;"> <!-- Increase width to 250px -->
<h6>Total Absent</h6>
<p id="absentCount" class="counter">0</p>
</div>
</div>
</div>
</div>
<div class="row center">
<div class="input-field col s12">
<select id="classSelect" class="browser-default custom-select" style="border: 1px solid #2196F3; border-radius: 10px;">
<option value="" disabled selected>Select class</option>
<option value="A">Class A</option>
<option value="B">Class B</option>
<option value="C">Class C</option>
<option value="D">Class D</option>
<option value="E">Class E</option>
</select>
</div>
</div>
<!-- Switch for Attendance -->
<div class="row center">
<div class="switch">
<label>
<span class="present-text" id="presentLabel">Present</span>
<input type="checkbox" id="attendanceSwitch">
<span class="lever"></span>
<span class="absent-text" id="absentLabel">Absent</span>
</label>
</div>
</div>
<!-- Scan QR Code Button -->
<!-- Your existing HTML code -->
<!-- Add the 'disabled' attribute to the button to initially disable it -->
<div class="row center">
<button id="scanButton" class="btn waves-effect waves-light" disabled>
Scan<i class="material-icons right">send</i>
</button>
</div>
<!-- QR Code Scanner -->
<div id="qr-reader" class="center">
</div>
<!-- Response Message -->
<div class="row center">
<div id="responseMessage" class="large-text"></div>
</div>
<audio id="beepSound" preload="auto">
<source src="https://www.orangefreesounds.com/wp-content/uploads/2021/12/Barcode-scanner-beep-sound.mp3" type="audio/mpeg">
</audio>
<!-- Your existing JavaScript code -->
<script>
document.addEventListener('DOMContentLoaded', function () {
var classSelect = document.getElementById('classSelect');
var scanButton = document.getElementById('scanButton');
var switchInput = document.getElementById('attendanceSwitch');
var isSubmitting = false;
var qrReader = null; // Initialize the QR scanner
M.FormSelect.init(classSelect); // Initialize Materialize form select
classSelect.addEventListener('change', function () {
// Enable the button when a class is selected
if (classSelect.value) {
scanButton.removeAttribute('disabled');
} else {
scanButton.setAttribute('disabled', 'disabled');
}
});
function resetColors() {
if (switchInput.checked) {
presentLabel.classList.remove('blue-text');
absentLabel.classList.add('red-text');
} else {
presentLabel.classList.add('blue-text');
absentLabel.classList.remove('red-text');
}
}
// Call the resetColors function to set the initial colors
resetColors();
switchInput.addEventListener('change', function() {
resetColors();
});
scanButton.addEventListener('click', function () {
if (isSubmitting) {
return; // If already submitting, exit
}
qrReader = new Html5QrcodeScanner("qr-reader", { fps: 10, qrbox: 250 });
qrReader.render(onScanSuccess);
function onScanSuccess(decodedText, decodedResult) {
if (isSubmitting) {
return; // If already submitting, exit
}
// Get the switch value (Present or Absent)
var switchValue = switchInput.checked ? 'Absent' : 'Present'; // Define switchValue here
// Increment the counter based on the switch value
if (switchValue === 'Present') {
presentCounter = parseInt(document.getElementById('presentCount').textContent) + 1;
document.getElementById('presentCount').textContent = presentCounter.toString();
} else if (switchValue === 'Absent') {
absentCounter = parseInt(document.getElementById('absentCount').textContent) + 1;
document.getElementById('absentCount').textContent = absentCounter.toString();
}
var classSelected = classSelect.value; // Capture the selected value
isSubmitting = true; // Set the flag to indicate submitting
document.getElementById('beepSound').play(); // Play the beep sound
document.getElementById('responseMessage').textContent = 'Sending Response...';
document.getElementById('responseMessage').classList.remove('green-text'); // Remove red text class
document.getElementById('responseMessage').classList.add('red-text'); // Add green text class
// Get the switch value (Present or Absent)
var switchValue = switchInput.checked ? 'Absent' : 'Present';
var classSelected = classSelect.value;
google.script.run.withSuccessHandler(function () {
document.getElementById('responseMessage').textContent = 'Attendance submitted successfully!';
document.getElementById('responseMessage').classList.remove('red-text'); // Remove red text class
document.getElementById('responseMessage').classList.add('green-text'); // Add green text class
isSubmitting = false; // Reset the flag
}).submitForm(classSelected, decodedText, switchValue); // Pass the QR code data and switch value
}
});
// Initialize Materialize components
var switchElems = document.querySelectorAll('.switch');
M.Switch.init(switchElems);
});
</script>
</body>
</html>
After inspecting the demo example from html5-qrcode, e.g. https://scanapp.org/
CSS: here
Adding the following CSS helped in overriding the Materialize styles:
button.html5-qrcode-element,
select.html5-qrcode-element,
button.scanapp-button {
appearance: none;
background-color: #FAFBFC;
border: 1px solid rgba(27, 31, 35, 0.15);
border-radius: 6px;
box-shadow: rgba(27, 31, 35, 0.04) 0 1px 0, rgba(255, 255, 255, 0.25) 0 1px 0 inset;
box-sizing: border-box;
color: #24292E;
cursor: pointer;
display: inline-block;
font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
font-size: 14px;
font-weight: 500;
line-height: 20px;
list-style: none;
padding: 6px 16px;
position: relative;
transition: background-color 0.2s cubic-bezier(0.3, 0, 0.5, 1);
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
vertical-align: middle;
white-space: nowrap;
word-wrap: break-word;
margin-bottom: 5px;
}