zxing-js refuses to scan barcodes

I’ve tried everything, other libraries (free ones, boss won’t pay the mad money commercial ones want), but it just won’t scan ean 13 codes. Will scan qr codes all day long. Tried setting the optiond for ean_13_read and ean_reader all to no avail. Quagga and the rest fail in the same way too, but not a shock as they seem to be mostly based on zxing anyway. Can anyone give me a bit of sample code that works? I’m working in dotnet 4.8 mvc, although this is really just pure html/js really. Thanks (hopefully) in advance.

Jim

Here’s my code, obviously doing other bits too. I’m just really after a sample that works!

@model Pocos.MCD_Stores

@{
    ViewBag.Title = "DoVisit";
}
<label id="recordCountLabel">Records Loaded: 0</label>
<br />
<h2>Do Visit</h2>

<!-- Add buttons to start scanning and manually trigger a scan -->
<button id="startScanButton">Start Scanner</button>
<button id="scanNowButton" style="display: none;">Scan it now!</button>
<button id="resetButton">Reset</button>
<br />
<!-- Add a video element for the barcode scanner -->
<video id="barcode-scanner" width="600" height="400" style="border: 1px solid gray; display: block;"></video>
<br />
<label id="scannedBarcodeLabel">Scanned Barcode: None</label>
<br />
<label id="productDetailsLabel">Product Details: None</label>
<br />
<!-- Add the dropdown for products -->
<select id="productDropdown" style="width: 100%;">
    <option value="">Select a product</option>
</select>

<link href="https://cdn.jsdelivr.net/npm/select2@('@')4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/@('@')zxing/library@('@')0.18.6/umd/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@('@')4.1.0-rc.0/dist/js/select2.min.js"></script>

<script>
    let selectedDeviceId;
    const codeReader = new ZXing.BrowserMultiFormatReader();
    console.log('ZXing code reader initialized');

    document.getElementById('startScanButton').addEventListener('click', () => {
        codeReader.listVideoInputDevices()
            .then(videoInputDevices => {
                selectedDeviceId = videoInputDevices.deviceId;
                codeReader.decodeFromVideoDevice(selectedDeviceId, 'barcode-scanner', { formats: [ZXing.BarcodeFormat.EAN_13] }, (result, err) => {
                    if (result) {
                        console.log('Barcode detected:', result);
                        document.getElementById('scannedBarcodeLabel').innerText = `Scanned Barcode: ${result.text}`;
                        handleScannedBarcode(result.text);
                    }
                    if (err && !(err instanceof ZXing.NotFoundException)) {
                        console.error('Error:', err);
                    }
                });
                document.getElementById('scanNowButton').style.display = 'block';
            })
            .catch(err => console.error('Error listing video input devices:', err));
    });

    document.getElementById('scanNowButton').addEventListener('click', () => {
        codeReader.decodeOnceFromVideoDevice(selectedDeviceId, 'barcode-scanner', { formats: [ZXing.BarcodeFormat.EAN_13] })
            .then(result => {
                if (result) {
                    console.log('Barcode detected:', result);
                    document.getElementById('scannedBarcodeLabel').innerText = `Scanned Barcode: ${result.text}`;
                    handleScannedBarcode(result.text);
                }
            })
            .catch(err => {
                if (err && !(err instanceof ZXing.NotFoundException)) {
                    console.error('Error:', err);
                }
            });
    });

    document.getElementById('resetButton').addEventListener('click', () => {
        codeReader.reset();
        document.getElementById('scannedBarcodeLabel').innerText = 'Scanned Barcode: None';
        document.getElementById('productDetailsLabel').innerText = 'Product Details: None';
        document.getElementById('scanNowButton').style.display = 'none';
    });

    // Function to handle the scanned barcode
    function handleScannedBarcode(barcode) {
        const productDbRequest = indexedDB.open('ProductDatabase', 1);

        productDbRequest.onsuccess = (event) => {
            const db = event.target.result;
            const transaction = db.transaction('products', 'readonly');
            const objectStore = transaction.objectStore('products');
            const getRequest = objectStore.get(barcode);

            getRequest.onsuccess = (event) => {
                const product = event.target.result;
                if (product) {
                    document.getElementById('productDetailsLabel').innerText = `Product Details: ${JSON.stringify(product)}`;
                    storeScannedProduct(product.Sku);
                } else {
                    document.getElementById('productDetailsLabel').innerText = `Product Details: Not found`;
                }
            };

            getRequest.onerror = (event) => {
                console.error('Error retrieving product:', event.target.error);
            };
        };

        productDbRequest.onerror = (event) => {
            console.error('Error opening ProductDatabase:', event.target.error);
        };
    }

    function customMatcher(params, data) {
        // If there are no search terms, return all of the data
        if ($.trim(params.term) === '') {
            return data;
        }

        // Make the search case-insensitive
        const term = params.term.toLowerCase();
        const text = data.text.toLowerCase();

        // Check if the term is found within the text
        if (text.indexOf(term) > -1) {
            return data;
        }

        // Return `null` if the term should not be displayed
        return null;
    }

    // Function to store the scanned product in the second IndexedDB
    function storeScannedProduct(sku) {
        const scannedDbRequest = indexedDB.open('scannedProductDatabase', 1);

        scannedDbRequest.onsuccess = (event) => {
            const db = event.target.result;
            const transaction = db.transaction('skuCounts', 'readwrite');
            const objectStore = transaction.objectStore('skuCounts');
            const getRequest = objectStore.get(sku);

            getRequest.onsuccess = (event) => {
                const record = event.target.result;
                if (record) {
                    record.Count += 1;
                    objectStore.put(record);
                } else {
                    objectStore.put({ Sku: sku, Count: 1 });
                }
            };

            getRequest.onerror = (event) => {
                console.error('Error retrieving scanned product:', event.target.error);
            };
        };

        scannedDbRequest.onerror = (event) => {
            console.error('Error opening scannedProductDatabase:', event.target.error);
        };
    }

    // Ensure the DOM is fully loaded before running the script
    document.addEventListener('DOMContentLoaded', (event) => {
        // Initialize the second IndexedDB
        initScannedProductDB()
            .then(db => {
                console.log('Second IndexedDB is ready to use.');
                // Retrieve the record count from localStorage and update the label
                const recordCount = localStorage.getItem('recordCount');
                if (recordCount) {
                    document.getElementById('recordCountLabel').innerText = `Records Loaded: ${recordCount}`;
                }
            })
            .catch(error => {
                console.error('Error initializing second IndexedDB:', error);
            });

        // Fetch products from IndexedDB and populate the dropdown
        fetchProductsFromIndexedDB().then(products => {
            products.sort((a, b) => {
                const descA = a.Desc !== "NULL" ? a.Desc.toLowerCase() : "";
                const descB = b.Desc !== "NULL" ? b.Desc.toLowerCase() : "";
                if (descA < descB) return -1;
                if (descA > descB) return 1;
                return 0;
            });

            const dropdown = $('#productDropdown');
            products.forEach(product => {
                const desc = product.Desc !== "NULL" ? product.Desc : "";
                const colour = product.Colour !== "NULL" ? product.Colour : "";
                const size = product.Size !== "NULL" ? product.Size : "";
                const option = new Option(`${desc} - ${colour} - ${size}`, product.Sku, false, false);
                dropdown.append(option);
            });
            dropdown.select2({
                placeholder: "Select a product",
                allowClear: true,
                matcher: customMatcher
            });
        }).catch(error => {
            console.error('Error fetching products:', error);
        });
    });

    // Function to initialize the second IndexedDB
    function initScannedProductDB() {
        return new Promise((resolve, reject) => {
            const request = indexedDB.open('scannedProductDatabase', 1);

            request.onupgradeneeded = (event) => {
                const db = event.target.result;
                const objectStore = db.createObjectStore('skuCounts', { keyPath: 'Sku' });
                objectStore.createIndex('Sku', 'Sku', { unique: true });
                objectStore.createIndex('Count', 'Count', { unique: false });
            };

            request.onsuccess = (event) => {
                console.log('Second IndexedDB initialized successfully.');
                resolve(event.target.result);
            };

            request.onerror = (event) => {
                reject(event.target.error);
            };
        });
    }

    // Function to fetch products from IndexedDB
    function fetchProductsFromIndexedDB() {
        return new Promise((resolve, reject) => {
            const request = indexedDB.open('ProductDatabase', 1);

            request.onsuccess = (event) => {
                const db = event.target.result;
                const transaction = db.transaction(['products'], 'readonly');
                const objectStore = transaction.objectStore('products');
                const products = [];

                objectStore.openCursor().onsuccess = (event) => {
                    const cursor = event.target.result;
                    if (cursor) {
                        products.push(cursor.value);
                        cursor.continue();
                    } else {
                        resolve(products);
                    }
                };

                objectStore.openCursor().onerror = (event) => {
                    reject(event.target.error);
                };
            };

            request.onerror = (event) => {
                reject(event.target.error);
            };
        });
    }
</script>