Barcode scanner troubleshooting
August 7, 2025 · AI Conversations
window.f7App = new Framework7({
el: '#app',
name: 'FossettsCircusApp',
theme: 'auto',
routes: [
{ path: '/', url: 'pages/home.html' },
{ path: '/staff-tickets/', url: 'pages/staff-tickets.html' },
{ path: '/staff-pay-terminal/', url: 'pages/staff-pay-terminal.html' },
{ path: '/staff-check-orders/', url: 'pages/staff-check-orders.html' },
{ path: '/event/:id/:dateId/', url: 'pages/event-details.html' }
]
});
// Create main view with default URL
window.mainView = f7App.views.create('.view-main', { url: '/' });
function startApp() {
navigator.splashscreen.hide();
initializeApp();
}
if (cordova.platformId === 'android' && cordova.plugins?.permissions) {
const permissions = cordova.plugins.permissions;
permissions.checkPermission(permissions.CAMERA, function (status) {
if (status.hasPermission) {
startApp();
} else {
permissions.requestPermission(
permissions.CAMERA,
function (status) {
status.hasPermission ? startApp() : navigator.app.exitApp();
},
function () {
navigator.app.exitApp();
}
);
}
});
} else {
startApp();
}
});
function initializeApp() {
window.TOKEN = 'fossettscircustoken';
window.eventId = -1;
window.eventDateId = -1;
window.ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';
let scanInProgress = false;
let alertVisible = false;
const scanConfig = {
preferFrontCamera: false,
showFlipCameraButton: true,
showTorchButton: true,
torchOn: false,
saveHistory: false,
prompt: "Place a code inside the scan area",
resultDisplayDuration: 500,
formats: "QR_CODE",
disableAnimations: true,
disableSuccessBeep: false
};
function showAlert(message, title = 'Alert') {
if (alertVisible) return;
alertVisible = true;
f7App.dialog.alert(message, title, () => {
alertVisible = false;
});
}
// Event Details Page
f7App.on('pageInit', function (page) {
if (page.name === 'event-details') {
const query = page.route.query;
const title = query.title || 'No Title';
const location = query.location || '';
const time = query.time || '';
const code = query.code || '';
eventDateId = query.eventDateId || -1;
eventId = query.eventId || -1;
page.$el.find('.event-title').text(title);
page.$el.find('.event-location').text(location);
page.$el.find('.event-time').text(time);
page.$el.find('input[name="code"]').val(code);
function sendCode(code, type) {
f7App.dialog.preloader(type === 'qr' ? 'Scanning code…' : 'Sending code…');
$('.scan').prop('disabled', true);
$.ajax({
url: `${ApiUrl}staff_scan`,
method: 'POST',
data: {
token: TOKEN,
event_date_id: eventDateId,
order_code: code
},
success: function (result) {
const apiResult = JSON.parse(result);
showAlert(apiResult.message, apiResult.result ? 'Scan Success' : 'Scan Failed');
},
error: function () {
showAlert('Something went wrong. Please try again.', 'Scan Failed');
},
complete: function () {
$('.scan').prop('disabled', false);
f7App.dialog.close();
scanInProgress = false;
}
});
}
function scanSuccess(result) {
if (!result.cancelled) {
if (eventDateId > -1) {
sendCode(result.text, 'qr');
} else {
showAlert('You must select an event date to scan tickets', 'Scan Failed');
scanInProgress = false;
}
} else {
showAlert('Scan was cancelled', 'Info');
scanInProgress = false;
}
}
function scanError(error) {
showAlert('Scanning failed: ' + error, 'Scan Failed');
scanInProgress = false;
}
page.$el.on('click', '.scan', function () {
if (scanInProgress) {
showAlert('Scan is already in progress. Please wait.', 'Hold On');
return;
}
scanInProgress = true;
cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
});
}
});
// Staff Tickets Page
f7App.on('pageInit', function (page) {
if (page.name === 'staff-tickets') {
loadEvents('yes');
page.$el.on('click', '.reload-events-staff', function () {
loadEvents('yes');
});
}
});
// Staff Pay Terminal Page
f7App.on('pageInit', function (page) {
if (page.name === 'staff-pay-terminal') {
page.$el.on('input', '#amountInput', function () {
const amount = parseFloat($(this).val());
const btn = $('#chargeBtn');
if (amount > 0) {
btn.removeClass('disabled:opacity-50').addClass('color-green');
btn.text('Charge €' + amount.toFixed(2));
} else {
btn.addClass('disabled:opacity-50').removeClass('color-green');
btn.text('Charge €0.00');
}
});
}
});
f7App.on('pageInit', function (page) {
if (page.name === 'staff-check-orders') {
function sendCodeAddon(code, type) {
f7App.dialog.preloader(type === 'qr' ? 'Scanning code…' : 'Sending code…');
$('.scan-addon').prop('disabled', true);
$.ajax({
url: `${ApiUrl}staff_scan_addon`,
method: 'POST',
data: {
token: TOKEN,
order_code: code
},
success: function (result) {
const apiResult = JSON.parse(result);
if(apiResult.result){
$('#addonsList').html(
apiResult.addons.map(function(addon) {
return '' + addon + '';
}).join('')
);
}else{
showAlert(apiResult.message, 'Scan Failed');
}
},
error: function () {
showAlert('Something went wrong. Please try again.', 'Scan Failed');
},
complete: function () {
$('.scan-addon').prop('disabled', false);
f7App.dialog.close();
scanInProgress = false;
}
});
}
function scanSuccessAddon(result) {
if (!result.cancelled) {
if (eventDateId > -1) {
sendCodeAddon(result.text, 'qr');
} else {
showAlert('You must select an event date to scan tickets', 'Scan Failed');
scanInProgress = false;
}
} else {
showAlert('Scan was cancelled', 'Info');
scanInProgress = false;
}
}
function scanErrorAddon(error) {
showAlert('Scanning failed: ' + error, 'Scan Failed');
scanInProgress = false;
}
page.$el.on('click', '.scan-addon', function () {
alert("ffafasf");
if (scanInProgress) {
showAlert('Scan is already in progress. Please wait.', 'Hold On');
return;
}
scanInProgress = true;
cordova.plugins.barcodeScanner.scan(scanSuccessAddon, scanErrorAddon, scanConfig);
});
}
});
}
function loadEvents(staff) {
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: { token: TOKEN },
success: function (result) {
const events = JSON.parse(result);
const $container = $('div.events').html('');
const weekday = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
if (events.result) {
events.data.forEach(val => {
const eventDatetime = new Date(val.event_datetime);
const dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
const timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
const dayname = weekday[eventDatetime.getDay()];
const code = `${val.event_id}.${val.event_date_id}.`;
const html = `
${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)}
0/500
`;
$container.append(html);
});
} else {
$container.html(`${events.message}`);
}
},
error: function () {
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function () {
f7App.dialog.close();
}
});
}
scan-addon click not working
—
### ✅ 1. **Missing or incorrect `page.name` in `pageInit`**
You're using this:
if (page.name === 'staff-check-orders') {
But this relies on the presence of:
<div class="page" data-name="staff-check-orders">
### ✅ Fix:
Ensure the `pages/staff-check-orders.html` file contains:
<div class="page" data-name="staff-check-orders">
If not present, `page.name` will be `undefined`, and the `scan-addon` logic won’t bind.
—
### ✅ 2. **`alert("ffafasf")` is triggered, but nothing else happens**
That confirms the click is firing, but the barcode scanner is not launching. Check:
#### a. **`cordova.plugins.barcodeScanner` is undefined**
This usually happens when:
– Plugin is not installed correctly
– Plugin is used before `deviceready`
– You're testing on the browser (barcode scanner only works on device/emulator)
### ✅ Fix:
Make sure the plugin is installed:
cordova plugin add phonegap-plugin-barcodescanner
And ensure you're testing **on a real device or emulator**, not in a browser.
—
### ✅ 3. **`scanInProgress` might already be true**
Once `scanInProgress = true`, further clicks are blocked unless it's reset. But if `eventDateId` is not set (i.e. -1), this block may happen:
if (eventDateId > -1) {
sendCodeAddon(result.text, 'qr');
} else {
showAlert('You must select an event date to scan tickets', 'Scan Failed');
scanInProgress = false;
}
So if `eventDateId` is still -1 on that page, scan won't proceed.
### ✅ Fix:
Set a valid `eventDateId` globally or from a field/query before scan:
window.eventDateId = 123; // assign this somewhere before scan is triggered
—
### ✅ 4. **Wrong selector or missing class**
Check your HTML has a button like:
<button class="scan-addon">Scan Addons</button>
—
### ✅ 5. **Permissions issue (Android)**
Make sure camera permission is granted before calling scanner.
You're handling this already on `deviceready`, so just make sure it's not skipped due to async errors.
—
### ✅ Summary of what you should check:
| Check | Solution |
|——-|———-|
| ✅ `data-name="staff-check-orders"` | Ensure in HTML |
| ✅ BarcodeScanner Plugin | Installed and works only on real device |
| ✅ `window.eventDateId` | Set a valid value before scanning |
| ✅ `.scan-addon` element | Must exist and be correctly classed |
| ✅ `cordova.plugins.barcodeScanner` | Confirm defined in `deviceready` |
| ✅ Button clickable | Check CSS/HTML doesn’t disable it |
—
Let me know if you want to debug with a `console.log()` chain or I can help prepare a minimal working `staff-check-orders.html` file.
Let's troubleshoot in order:
—
### ✅ 1. **Ensure your page has `data-name="staff-check-orders"`**
In your `pages/staff-check-orders.html`, the top-level “ should look like this:
<div class="page" data-name="staff-check-orders">
> ⚠️ If `data-name` is missing, then `page.name` will be `undefined`, and your `pageInit` condition won't match.
—
### ✅ 2. **Verify `.scan-addon` button is inside the page**
Make sure your button exists and is inside the `.page` element. For example:
<div class="page" data-name="staff-check-orders">
...
<button class="scan-addon">Scan Addon</button>
</div>
—
### ✅ 3. **Make sure no early event conflicts are preventing the click handler**
To confirm the `pageInit` is even firing, add a log:
f7App.on('pageInit', function (page) {
console.log('pageInit:', page.name); // Add this
if (page.name === 'staff-check-orders') {
console.log('Staff Check Orders Init'); // And this
> ✅ If **you don’t see this in the console**, your `data-name` is wrong or missing.
—
### ✅ 4. **Add a failsafe delegated click binding as a backup**
Framework7 sometimes replaces page DOM after init. You can add a fallback listener outside `pageInit`:
$(document).on('click', '.page[data-name="staff-check-orders"] .scan-addon', function () {
console.log('Delegated scan-addon clicked');
});
This helps test if the button is rendered but missing binding due to timing.
—
### ✅ 5. **Inspect for typos in the button class or misplaced HTML**
Double-check that:
– Class name is spelled exactly `.scan-addon`
– There’s no duplication or nested `form` preventing default behavior
—
### 🔍 Final Debug Checklist
| Test | Expectation |
|——|————-|
| `data-name="staff-check-orders"` | ✅ Present |
| `console.log('Staff Check Orders Init')` | ✅ Printed |
| `.scan-addon` button | ✅ Visible and inside page |
| Delegated click via `$(document).on()` | ✅ Fires as backup |
| `eventDateId > -1` | ✅ Set before scanning |
—
Would you like me to generate a minimal working HTML example for `staff-check-orders.html` with the button and scan logic? That might help confirm.
> ✅ `loadEvents()` works on the Home page normally…
> ❌ But **on first launch after installation**, events don't load
> ✅ When reopening the app later, they **do** load
This is a common issue in **Cordova + Framework7** hybrid apps and is usually caused by **one of the following**:
—
### ✅ 1. **`loadEvents()` is called before Framework7 view is fully initialized**
You call `loadEvents('yes')` inside this block:
f7App.on('pageInit', function (page) {
if (page.name === 'staff-tickets') {
loadEvents('yes');
}
});
But if `Framework7` hasn’t finished setting up views or routing properly on first launch, that `pageInit` may not trigger as expected.
### ✅ Fix:
Move `loadEvents()` call into `viewDidEnter` or `pageAfterIn` instead of `pageInit`:
f7App.on('pageAfterIn', function (page) {
if (page.name === 'staff-tickets') {
loadEvents('yes');
}
});
or even more reliably:
f7App.views.main.router.on('routeChange', function (newRoute, oldRoute, resolve) {
if (newRoute.name === 'staff-tickets') {
loadEvents('yes');
}
});
—
### ✅ 2. **Home page not triggering `pageInit` because it's the default route**
Framework7 might not trigger `pageInit` for the home page (`/`) on the **first launch** if it's pre-rendered.
### ✅ Fix:
Manually call `loadEvents()` in `initializeApp()` if the homepage is loaded by default:
function startApp() {
navigator.splashscreen.hide();
initializeApp();
// Manually trigger loadEvents for homepage on first load
const currentRoute = mainView.router.currentRoute;
if (currentRoute.path === '/' || currentRoute.name === 'home') {
loadEvents('yes');
}
}
Or detect inside `initializeApp()` using:
f7App.on('init', () => {
const currentPage = f7App.views.main.router.currentPageEl;
if ($(currentPage).attr('data-name') === 'home') {
loadEvents('yes');
}
});
—
### ✅ 3. **Cordova plugin not ready yet (especially camera/permissions)**
If `loadEvents()` relies on `TOKEN`, `ApiUrl`, or permissions (camera), and those aren’t set until after `deviceready`, then your first call may fail silently.
### ✅ Fix:
Ensure `loadEvents()` only runs after:
– `cordova.platformId` is ready
– Permissions are granted
– All globals like `TOKEN` are set
—
### ✅ 4. **Splash screen not hidden fast enough, blocking UI rendering**
If `navigator.splashscreen.hide()` is delayed or not called properly, the app looks stuck.
### ✅ Fix:
Move `navigator.splashscreen.hide()` *after* your `loadEvents()` call inside `startApp()`:
function startApp() {
initializeApp();
navigator.splashscreen.hide();
}
Or delay splashscreen hide using a short timeout:
function startApp() {
initializeApp();
setTimeout(() => navigator.splashscreen.hide(), 500); // Optional
}
—
### ✅ Recommended Fix Summary
function startApp() {
initializeApp();
// Manually load events if home page is loaded first
const route = mainView.router.currentRoute;
if (route.path === '/' || route.name === 'home') {
loadEvents('yes');
}
navigator.splashscreen.hide();
}
—
Would you like me to help you implement a `viewDidEnter` or `pageAfterIn` hook for the home page to ensure `loadEvents()` is always triggered reliably?
{ path: '/', url: 'pages/home.html' }
And **the page has**:
<div class="page" data-name="home">
Then here’s how you can **reliably trigger `loadEvents('yes')`** even on the **first app launch after install**.
—
### ✅ Final Recommended Fix
Inside your `initializeApp()` function, **add this block** to ensure `loadEvents()` runs if the user lands on the home page right after app install:
f7App.on('pageAfterIn', function (page) {
if (page.name === 'home') {
console.log('Home pageAfterIn → calling loadEvents()');
loadEvents('yes');
}
});
> `pageAfterIn` is **more reliable than `pageInit`** for the **initial page** because Framework7 sometimes skips `pageInit` for the first rendered page.
—
### ✅ Optional: Add fallback inside `startApp()` for extra safety
If for some reason the route is already active before the hook above binds:
function startApp() {
initializeApp();
// If app starts on home page, load events
const route = mainView.router.currentRoute;
if (route.path === '/' || route.name === 'home') {
console.log('Detected home page on startup → calling loadEvents()');
loadEvents('yes');
}
navigator.splashscreen.hide();
}
—
### 🔄 Summary
– ✅ Use `pageAfterIn` for consistent behavior when navigating to `/`
– ✅ Use `currentRoute` check in `startApp()` for very first launch fallback
– ✅ Make sure your home page HTML has:
<div class="page" data-name="home">
Let me know if you'd like me to review your `home.html` or enhance the UI while loading events.