javascripthtmlcssgoogle-apps-scriptmaterialize

Conflict between Materialize CSS and html5-qrcode Library - Webapp created with Google Apps Scripts


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)

enter image description here

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:

enter image description here

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>


Solution

  • 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:

    enter image description here

    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;
        }