Auto load staff events
August 7, 2025 · AI Conversations
{
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {
$('.staff-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`
${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}
0/500
`);
//$('.staff-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}Collect Payment`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});
remove click event just run default
Here’s the **modified version** of your code:
function loadStaffEvents() {
f7App.dialog.preloader('Loading events...');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result, status, xhr) {
console.log(result);
var events = JSON.parse(result);
if (events.result) {
$('.staff-screen ul.events').html('');
$('.staff-screen div.events').html('');
const weekday = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
$.each(events.data, function(i, val) {
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname = weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`
<div class="space-y-4 mb-4" data-event-id="${val.event_id}" data-event-date-id="${val.event_date_id}">
<div class="rounded-lg border border-border/40 card bg-background hover:shadow-lg transition-shadow cursor-pointer">
<div class="p-6">
<div class="flex justify-between items-center">
<div>
<h3 class="text-xl font-semibold">${val.venue_full}</h3>
<p class="text-gray-600">${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} -
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}</p>
</div>
<div class="text-right">
<div class="inline-flex items-center rounded-full border font-semibold transition-all focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 text-foreground border-border px-2.5 py-0.5 text-xs">
0/500
</div>
</div>
</div>
</div>
</div>
</div>`);
});
} else {
$('.events').html(`<div class="no-result-item text-center bg-info text-white">${events.message}</div>`);
}
},
error: function(xhr, status, error) {
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function() {
f7App.dialog.close();
}
});
}
// Call it directly on page load or page init
$(document).ready(function() {
loadStaffEvents();
});
// OR if you're using Framework7 page event:
$(document).on('page:init', '.page[data-name="staff"]', function (e) {
loadStaffEvents();
});
✅ **Benefits:**
– No `.click()` event needed.
– You control where and when the event data loads.
– You can still reuse `loadStaffEvents()` anywhere else (e.g. refresh button).
### ✅ What we’ll do:
1. User logs in by entering credentials (you can skip server check for simplicity).
2. Store a flag (e.g., `isLoggedIn = true`) in `localStorage`.
3. On app start, check `localStorage` — if logged in, redirect to home.
4. Else show login screen.
—
### 🔧 1. HTML (login.html)
<!-- login.html -->
<div class="page" data-name="login">
<div class="page-content login-screen-content">
<div class="block">
<h2>Login</h2>
<div class="list">
<ul>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label">Username</div>
<div class="item-input-wrap">
<input type="text" id="username" placeholder="Enter username">
</div>
</div>
</div>
</li>
<li>
<div class="item-content item-input">
<div class="item-inner">
<div class="item-title item-label">Password</div>
<div class="item-input-wrap">
<input type="password" id="password" placeholder="Enter password">
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block">
<a href="#" class="button button-fill login-button">Login</a>
</div>
</div>
</div>
</div>
—
### 🔌 2. JavaScript Logic
document.addEventListener('deviceready', function () {
// Initialize Framework7 app
var f7App = new Framework7({
el: '#app',
name: 'LoginApp',
theme: 'auto',
routes: [
{ path: '/', url: 'pages/home.html' },
{ path: '/login/', url: 'pages/login.html' }
]
});
var mainView = f7App.views.create('.view-main');
// Redirect if already logged in
if (localStorage.getItem('isLoggedIn') === 'true') {
mainView.router.navigate('/');
} else {
mainView.router.navigate('/login/');
}
// Handle login button click
$(document).on('click', '.login-button', function () {
var username = $('#username').val();
var password = $('#password').val();
if (username === 'admin' && password === 'admin') {
localStorage.setItem('isLoggedIn', 'true');
mainView.router.navigate('/');
} else {
f7App.dialog.alert('Invalid credentials', 'Login Failed');
}
});
});
—
### 🏠 3. Home Page (home.html)
<!-- home.html -->
<div class="page" data-name="home">
<div class="navbar">
<div class="navbar-inner">
<div class="title">Home</div>
<div class="right">
<a href="#" class="link logout-button">Logout</a>
</div>
</div>
</div>
<div class="page-content">
<div class="block">
<h2>Welcome!</h2>
<p>This is the home page.</p>
</div>
</div>
</div>
—
### 🚪 4. Logout Logic
$(document).on('click', '.logout-button', function () {
localStorage.removeItem('isLoggedIn');
f7App.views.main.router.navigate('/login/');
});
—
### ✅ Summary
– 🔐 You simulate login using localStorage.
– 🔁 Redirect to home if already logged in.
– 🚪 Logout clears the login status.
Let me know if you want to include a backend check via AJAX too.
—
### ✅ Requirements:
– Android Studio **Hedgehog** or later
– USB cable (for initial setup)
– Phone running Android 11 or above (preferably)
– Developer options & USB debugging enabled
—
### 🔄 Option 1: **ADB Pairing via QR Code (No Cable Needed)**
#### 🔧 Step-by-Step Instructions:
1. **Enable Developer Options** on your phone:
– Go to **Settings > About phone** → tap **Build number** 7 times
– Go to **Settings > System > Developer options**
2. **Enable Wireless Debugging**:
– In **Developer options**, turn on **Wireless debugging**
3. **Pair using QR code**:
– In Android Studio:
– Go to **Device Manager** (right sidebar) → Click **+ Pair using Wi-Fi**
– Choose **Pair using QR code**
– On your Android device:
– Still in **Wireless Debugging** → Tap **Pair device with QR code**
– Scan the QR code shown in Android Studio
4. ✅ Done! Your real device will show up under **Connected Devices** in Android Studio.
—
### 🔁 Option 2: **ADB Over Wi-Fi Using IP and Port (Manual)**
If QR pairing fails, use this method with a USB cable for the first time:
adb usb # (optional) ensure USB connection
adb tcpip 5555
adb connect <DEVICE_IP>:5555
You can get the IP from:
– `adb shell ip route`
– or phone’s Wi-Fi settings.
—
### 📌 Notes:
– QR Code method uses **secure pairing** (Android 11+).
– Works even without USB if Wireless Debugging is supported.
– Make sure both PC and phone are on the **same Wi-Fi network**.
—
Let me know if you want to mirror the screen or just run/debug apps.
—
### ✅ Steps to Use Paired Android Device in Android Studio
#### 📱 1. **Check Device Connection**
– Open **Android Studio**
– Go to **Device Manager** (right toolbar)
– Your phone should appear under **"Connected Devices"**
– Name like `Pixel 6a (Wi-Fi)` or similar
– If not, open **Terminal** and run:
adb devices
You should see your device listed as `device`.
—
#### ▶️ 2. **Run Your App on the Device**
– Open your Android project
– Click the **Run ▶️** button or press `Shift + F10`
– In the **"Select Deployment Target"** window, choose your **Wi-Fi connected phone**
– Click **OK** or **Run**
Android Studio will build the app and install it on your device wirelessly.
—
#### 🔁 3. **Enable Instant Run (Optional for Speed)**
– Go to **File > Settings > Build, Execution, Deployment > Deployment**
– Enable **"Apply changes…"** to push code without reinstalling the app
—
#### 🚫 4. **To Disconnect Device Later**
– On your phone:
Go to **Developer options > Wireless debugging** → Tap **Forget all devices**
– Or run in terminal:
adb disconnect <ip>:port
—
### 🛠 Troubleshooting
| Issue | Solution |
|——-|———-|
| Device not showing | Restart Android Studio, verify `adb devices` shows your phone |
| App not installing | Check if device is unlocked and has enough storage |
| QR pairing fails | Try with USB cable and use `adb tcpip 5555` |
—
Let me know if you want to **mirror screen**, **debug logs**, or use **ADB commands** directly.
—
### ✅ How to Run Your App on the Paired Android Device
#### 🔁 Step-by-Step:
1. **Open Your Project** in Android Studio.
2. At the top toolbar, locate the **Device dropdown** (next to the green ▶️ Run button).
3. From the dropdown, **select your connected device**:
It should appear like:
`Pixel 6a (Wi-Fi)` or `SM-M14 (192.168.x.x:5555)` depending on your phone.
4. Click the **Run ▶️ button** or press `Shift + F10`.
5. Android Studio will:
– **Build the APK**
– **Install it wirelessly**
– **Launch the app automatically** on your phone
—
### 📱 On Your Phone
– Ensure the screen is **unlocked**
– You’ll see your app open once it’s successfully deployed
—
### 🛠 If the device is not listed in dropdown:
– Try clicking **Run ▶️** anyway — a popup will appear to **select device**
– If still not listed:
– Go to **View > Tool Windows > Device Manager**
– Or run `adb devices` to verify it’s connected as `device`
—
Let me know if:
– You want to enable **live logcat logging**
– You want to **debug** the app using breakpoints
– You need **multiple devices or emulator + real device setup**
{
f7App.dialog.alert('Something went wrong. Please try again.'+error+status+xhr, 'Error');
}
how to get detailed error
– `xhr.status` – HTTP status code (e.g., 404, 500)
– `xhr.statusText` – status description (e.g., "Not Found")
– `xhr.responseText` – raw server response
– `error` – general error message from jQuery
– `status` – error type (like "error", "timeout", "parsererror")
—
### ✅ Updated Error Function (Verbose Logging):
error: function(xhr, status, error) {
let detailedMessage = `
❌ Status: ${xhr.status} (${xhr.statusText})n
🧠 Error Type: ${status}n
📩 Response: ${xhr.responseText || 'No response'}n
🧾 Error: ${error}
`;
console.error("AJAX Error Details", {
status: xhr.status,
statusText: xhr.statusText,
responseText: xhr.responseText,
error: error,
fullXhr: xhr
});
f7App.dialog.alert(detailedMessage, 'Error');
}
—
### 🛠 Extra Tip for JSON Responses
If your backend returns JSON and you're expecting `result.message`, check:
try {
const json = JSON.parse(xhr.responseText);
console.log("Parsed JSON:", json);
} catch (e) {
console.warn("Response is not valid JSON");
}
—
This gives you a **clear breakdown** inside both:
– The **alert for the user**
– The **console for debugging**
Let me know if you want to log it to a remote server or alert with a friendly error message instead.
—
### 🚨 Causes of `xhr.status == 0`:
| Cause | Description |
|——-|————-|
| ❌ **CORS blocked** | You're making a cross-origin request without proper headers |
| 📡 **No internet / disconnected** | Device has no connection or server is unreachable |
| 🔒 **HTTPS → HTTP** | Mixed content (HTTPS site calling HTTP URL) — blocked by browser |
| ⌛ **Request timed out** | Backend took too long to respond |
| 🔂 **Manually aborted** | AJAX call was aborted using `xhr.abort()` |
| 📁 **Wrong `url` or file path** | Endpoint doesn’t exist or returns a blank response |
—
### ✅ How to Debug It
Update your error block like this to get more clues:
error: function(xhr, status, error) {
console.error("AJAX Error", {
status: xhr.status, // 0
statusText: xhr.statusText, // Often empty
responseText: xhr.responseText, // May be empty
readyState: xhr.readyState, // 0-4
errorThrown: error,
url: this.url // URL being requested
});
f7App.dialog.alert(`
❌ AJAX failed!
Status: ${xhr.status}
ReadyState: ${xhr.readyState}
Error: ${error}
Response: ${xhr.responseText || 'No response'}
`, 'Error');
}
—
### 🛠 Solutions to Try
1. **Check your `url` value**:
url: `${ApiUrl}today` // Make sure ApiUrl is set correctly
– Try logging `ApiUrl` before the AJAX call to ensure it's not undefined.
2. **Add CORS headers on server (if using PHP)**:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
3. **Use HTTPS for both frontend and backend**
If your app is served over HTTPS, your API must also be HTTPS.
4. **Test API directly**:
– Open browser dev tools → Network tab
– Paste the API URL directly to see if it responds
5. **Try using `cordova-plugin-whitelist` (if in Cordova)**:
If you're running this inside a Cordova app:
<access origin="*" />
<allow-navigation href="*" />
<allow-intent href="*" />
And ensure plugin is installed:
cordova plugin add cordova-plugin-whitelist
—
Let me know if you're testing on mobile, localhost, or remote server — I can give more specific advice.
if (cordova.platformId === 'android') {
var permissions = cordova.plugins.permissions;
permissions.checkPermission(permissions.CAMERA, function (status) {
if (!status.hasPermission) {
// Request permission
permissions.requestPermission(
permissions.CAMERA,
function (status) {
if (status.hasPermission) {
navigator.splashscreen.hide(); // Hide splash after permission
initializeApp(); // Proceed with your app
} else {
navigator.app.exitApp(); // Exit if denied
}
},
function () {
navigator.app.exitApp(); // Exit on request error
}
);
} else {
navigator.splashscreen.hide();
initializeApp(); // Permission already granted
}
});
} else {
navigator.splashscreen.hide(); // For browser/iOS fallback
initializeApp();
}
}, false);
function initializeApp() {
let TOKEN = 'fossettscircustoken';
var eventId = -1;
var eventDateId = -1;
let ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';
var scanConfig = {
preferFrontCamera : false, // iOS and Android
showFlipCameraButton : true, // iOS and Android
showTorchButton : true, // iOS and Android
torchOn: false, // Android, launch with the torch switched on (if available)
saveHistory: false, // Android, save scan history (default false)
prompt : "Place a code inside the scan area", // Android
resultDisplayDuration: 500, // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500
formats : "QR_CODE", // default: all but PDF_417 and RSS_EXPANDED
//orientation : "landscape", // Android only (portrait|landscape), default unset so it rotates with the device
disableAnimations : true, // iOS
disableSuccessBeep: false // iOS and Android
};
$(document).ready(function()
{
$(document).on('page:init', '.page[data-name="home"]', function () {
$('#customer-access').on('click', function () {
f7App.views.main.router.navigate('/customer/');
});
$('#staff-access').on('click', function () {
f7App.views.main.router.navigate('/staff-login/');
});
});
$(document).on('page:init', '.page[data-name="staff-pay-terminal"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
$(document).on('input', '#amountInput', function () {
const amount = parseFloat($(this).val());
const btn = $('#chargeBtn');
if (amount > 0) {
btn.removeClass('disabled color-gray').addClass('color-green');
btn.text('Charge €' + amount.toFixed(2));
} else {
btn.addClass('disabled color-gray').removeClass('color-green');
btn.text('Charge €0.00');
}
});
})
var staffEventsLoaded = false;
$(document).on('page:init', '.page[data-name="staff-tickets"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
$(document).on('click', '.reload-events-staff', function()
{
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {
$('.staff-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`
${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}
0/500
`);
//$('.staff-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}Collect Payment`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});
// load events click
$('.reload-events-staff').trigger('click');
$(document).on('click', '.logout-staff', function()
{
localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-check-orders"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
});
$(document).on('page:init', '.page[data-name="staff-dashboard"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-tickets').on('click', function () {
f7App.views.main.router.navigate('/staff-tickets/');
});
$('#open-pay-terminal').on('click', function () {
f7App.views.main.router.navigate('/staff-pay-terminal/');
});
$('#check-orders').on('click', function () {
f7App.views.main.router.navigate('/staff-check-orders/');
});
// load events click
$('.reload-events-staff').trigger('click');
$(document).on('click', '.logout-staff', function()
{
localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-login"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-login-form').on('submit', function (e) {
e.preventDefault();
var email = $('#staff-email').val();
var password = $('#staff-password').val();
f7App.dialog.preloader('Logging in…');
$.ajax({
url: `${ApiUrl}staff_login`,
method: 'POST',
data: {
token: TOKEN,
email: email,
password: password
},
success: function (result, status, xhr) {
var apiResult = JSON.parse(result);
if (apiResult.result) {
f7App.views.main.router.navigate('/staff/');
} else {
$('#login-result').html(apiResult.message);
}
},
error: function (xhr, status, error) {
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function () {
// ✅ Hide preloader after AJAX completes
f7App.dialog.close();
}
});
});
});
// Page: Customer
$(document).on('page:init', '.page[data-name="customer"]', function () {
// 👇 Ensure Bootstrap re-binds modal events
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
var sendCode = function(code)
{
$('.scan').prop('disabled', true);
$('.manually').prop('disabled', true);
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ code +' sent to boxoffice, plase wait…');
$.ajax({
url: `${ApiUrl}scan`,
method: 'POST',
data: {
token: TOKEN,
event_date_id: eventDateId,
order_code: code
},
success: function(result,status,xhr)
{
var apiResult = JSON.parse(result);
if ( apiResult.result )
{
$('#scan-result').removeClass('bg-dark').addClass('bg-success').html(apiResult.message+''+apiResult.seating+''+apiResult.tickets);
// reset input to set next code
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html(apiResult.message);
}
},
error: function(xhr,status,error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ result.text +' could not be sent to boxoffice, please try again');
},
complete: function()
{
$('.scan').prop('disabled', false);
$('.manually').prop('disabled', false);
}
});
}
var scanError = function (error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html("Scanning failed: " + error);
f7App.popup.open('#modal-scan-result');
};
var scanSuccess = function(result)
{
if (! result.cancelled )
{
if (eventDateId > -1)
{
sendCode(result.text);
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('You must select an event date to scan tickets');
}
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Scan was cancelled');
}
f7App.popup.open('#modal-scan-result');
};
$(document).on('click', '.reload-events', function()
{
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {
$('.customer-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
// $('.customer-screen ul.events').append(`
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}
//
//
// `);
$('.customer-screen div.events').append(`
${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}
0/500
`);
// $('.customer-screen ul.events').append(`
//
//
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
// ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} –
// ${val.venue_title} – ${val.venue_full}
//
//
//
//
// `);
// $('.customer-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.'+xhr.statusText+xhr.status, 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});
// load events click
$('.reload-events').trigger('click');
$(document).on('click', '.customer-screen .events .list-group-item', function()
{
$('.customer-screen .events .list-group-item').removeClass('active');
$(this).addClass('active');
$('#scan-info').html($(this).html());
eventId = $(this).attr('data-event-id');
eventDateId = $(this).attr('data-event-date-id');
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
// first scan on event date click
//cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
f7App.popup.open('#modal-scan-result');
});
$(document).on('click', '.scan', function()
{
cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
});
$(document).on('click', '.manually', function()
{
sendCode($('[name="code"]').val());
});
});
// $('ons-button').on('click', function(e) {
// ons.notification.alert('Button is tapped!');
// })
});
}
above code for fetch event for customer section stopped working its return ajax status 0 in andrdroind but when run in browser its work well
—
### ✅ Root Cause (Most Likely):
Your AJAX call is to:
let ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';
While this works in the **browser**, Cordova apps run in a **WebView sandbox**, and:
– Do **not allow external domains** unless explicitly permitted.
– Require **CORS headers** on the server.
– May block **HTTPS → HTTP** (or vice versa) if not handled correctly.
—
### ✅ Fix It Step-by-Step:
—
#### ✅ 1. Add Cordova Whitelist Plugin (if not added):
Run:
cordova plugin add cordova-plugin-whitelist
Then in `config.xml`, add:
<allow-navigation href="*" />
<access origin="*" />
<allow-intent href="*" />
—
#### ✅ 2. Ensure AndroidManifest Permissions:
Inside your `AndroidManifest.xml`, confirm:
<uses-permission android:name="android.permission.INTERNET" />
—
#### ✅ 3. Server Must Allow CORS
Your server (`staging.fossettscircus.com`) **must send the right headers**:
In your PHP API backend (`index.php/api/today`), add:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
Place these at the **very top** before any output.
—
#### ✅ 4. Debug with More Detail
In your `.ajax()` `error` callback, replace with this to inspect further:
error: function(xhr, status, error) {
console.error("XHR ERROR:", {
status: xhr.status,
statusText: xhr.statusText,
responseText: xhr.responseText,
readyState: xhr.readyState,
errorThrown: error,
headers: xhr.getAllResponseHeaders()
});
f7App.dialog.alert(`
❌ AJAX Failed
Status: ${xhr.status} (${xhr.statusText})
Error: ${error}
Response: ${xhr.responseText}
`, 'Error');
}
—
#### 🧪 5. Test with a Localhost Server on Android Device
Sometimes Android WebView blocks requests to `localhost` or `https` servers with self-signed SSL. Try changing:
let ApiUrl = 'http://your-lan-ip/boxoffice/index.php/api/';
// or deploy a test endpoint on a public URL with HTTPS and CORS enabled
—
### 🧠 Extra Tips
– If you're using `content-security-policy`, loosen it for dev:
<meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline' 'unsafe-eval' data: gap:;">
– Android 9+ blocks **cleartext (HTTP)** traffic by default. You must allow it in `network_security_config.xml`.
—
### ✅ Final Suggestion:
If you want, I can test the live `https://staging.fossettscircus.com/boxoffice/index.php/api/today` URL for proper CORS headers. Just let me know.
Let me know how you're running it (emulator, real device, APK) and I’ll tailor the fix more closely.
but I think I have updated android sdk
– ✅ CORS headers are present,
– ✅ It works in `cordova run browser`,
– ❌ But fails on **real Android device or emulator** with `status = 0`,
– 💡 And you've **recently updated Android SDK**,
You're likely hitting a **WebView security change in newer Android SDK versions**, especially Android 10+ (SDK 29+).
—
### ✅ Checklist to Fix Cordova AJAX status 0 on Android:
#### ✅ 1. **Enable `usesCleartextTraffic`** if using HTTP (not needed for HTTPS)
If your API URL is `http://` (not `https://`), Android 9+ blocks it by default.
In `AndroidManifest.xml` inside “:
android:usesCleartextTraffic="true"
And define this inside `res/xml/network_security_config.xml`:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
Then reference it:
<application
android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true"
...>
✅ **Not needed for HTTPS**, but if your domain uses a **self-signed SSL** or weak certificate, that can cause issues too.
—
#### ✅ 2. **Force Cordova to Use Legacy WebView**
If you're using a new Android WebView (based on Chromium), it may enforce stricter network rules.
Add to `config.xml`:
<preference name="AndroidInsecureFileModeEnabled" value="true" />
<preference name="AndroidXEnabled" value="true" />
You can also try forcing a compatible WebView:
cordova plugin add cordova-plugin-androidx-adapter
—
#### ✅ 3. **Inspect Dev Logs via `adb logcat`**
Run this in terminal to see real-time logs:
adb logcat | grep chromium
This will often reveal:
– Mixed content errors
– Certificate validation issues
– Blocked cross-origin requests
—
#### ✅ 4. **Test with Postman or Mobile Browser on Same Device**
Use your **phone’s browser** to open:
https://staging.fossettscircus.com/boxoffice/index.php/api/today
If the result is empty or SSL warns you — then the problem is with:
– SSL cert (not fully trusted)
– Invalid DNS or redirect
—
#### ✅ 5. **Try Running With Older Target SDK**
Temporarily change `platforms/android/app/build.gradle`:
targetSdkVersion = 30
Or in `config.xml`:
<preference name="android-targetSdkVersion" value="30" />
Then run:
cordova platform remove android
cordova platform add android@latest
cordova build android
—
### 🧪 Final Debug Help
If still stuck, add a temporary test API with:
<?php
header("Access-Control-Allow-Origin: *");
echo json_encode(["result" => true, "message" => "It works!"]);
Then test that in your app to isolate the API issue vs. SDK/WebView issue.
—
Let me know your:
– Android version (10/11/12/etc.)
– Cordova version
– Target SDK in `AndroidManifest.xml`
And I’ll guide you precisely!
if (cordova.platformId === 'android') {
var permissions = cordova.plugins.permissions;
permissions.checkPermission(permissions.CAMERA, function (status) {
if (!status.hasPermission) {
// Request permission
permissions.requestPermission(
permissions.CAMERA,
function (status) {
if (status.hasPermission) {
navigator.splashscreen.hide(); // Hide splash after permission
initializeApp(); // Proceed with your app
} else {
navigator.app.exitApp(); // Exit if denied
}
},
function () {
navigator.app.exitApp(); // Exit on request error
}
);
} else {
navigator.splashscreen.hide();
initializeApp(); // Permission already granted
}
});
} else {
navigator.splashscreen.hide(); // For browser/iOS fallback
initializeApp();
}
}, false);
function initializeApp() {
let TOKEN = 'fossettscircustoken';
var eventId = -1;
var eventDateId = -1;
let ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';
var scanConfig = {
preferFrontCamera : false, // iOS and Android
showFlipCameraButton : true, // iOS and Android
showTorchButton : true, // iOS and Android
torchOn: false, // Android, launch with the torch switched on (if available)
saveHistory: false, // Android, save scan history (default false)
prompt : "Place a code inside the scan area", // Android
resultDisplayDuration: 500, // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500
formats : "QR_CODE", // default: all but PDF_417 and RSS_EXPANDED
//orientation : "landscape", // Android only (portrait|landscape), default unset so it rotates with the device
disableAnimations : true, // iOS
disableSuccessBeep: false // iOS and Android
};
$(document).ready(function()
{
$(document).on('page:init', '.page[data-name="home"]', function () {
$('#customer-access').on('click', function () {
f7App.views.main.router.navigate('/customer/');
});
$('#staff-access').on('click', function () {
f7App.views.main.router.navigate('/staff-login/');
});
});
$(document).on('page:init', '.page[data-name="staff-pay-terminal"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
$(document).on('input', '#amountInput', function () {
const amount = parseFloat($(this).val());
const btn = $('#chargeBtn');
if (amount > 0) {
btn.removeClass('disabled color-gray').addClass('color-green');
btn.text('Charge €' + amount.toFixed(2));
} else {
btn.addClass('disabled color-gray').removeClass('color-green');
btn.text('Charge €0.00');
}
});
})
var staffEventsLoaded = false;
$(document).on('page:init', '.page[data-name="staff-tickets"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
$(document).on('click', '.reload-events-staff', function()
{
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {
$('.staff-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`
${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}
0/500
`);
//$('.staff-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}Collect Payment`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});
// load events click
$('.reload-events-staff').trigger('click');
$(document).on('click', '.logout-staff', function()
{
localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-check-orders"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/staff/');
});
});
$(document).on('page:init', '.page[data-name="staff-dashboard"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-tickets').on('click', function () {
f7App.views.main.router.navigate('/staff-tickets/');
});
$('#open-pay-terminal').on('click', function () {
f7App.views.main.router.navigate('/staff-pay-terminal/');
});
$('#check-orders').on('click', function () {
f7App.views.main.router.navigate('/staff-check-orders/');
});
// load events click
$('.reload-events-staff').trigger('click');
$(document).on('click', '.logout-staff', function()
{
localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-login"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-login-form').on('submit', function (e) {
e.preventDefault();
var email = $('#staff-email').val();
var password = $('#staff-password').val();
f7App.dialog.preloader('Logging in…');
$.ajax({
url: `${ApiUrl}staff_login`,
method: 'POST',
data: {
token: TOKEN,
email: email,
password: password
},
success: function (result, status, xhr) {
var apiResult = JSON.parse(result);
if (apiResult.result) {
f7App.views.main.router.navigate('/staff/');
} else {
$('#login-result').html(apiResult.message);
}
},
error: function (xhr, status, error) {
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function () {
// ✅ Hide preloader after AJAX completes
f7App.dialog.close();
}
});
});
});
// Page: Customer
$(document).on('page:init', '.page[data-name="customer"]', function () {
// 👇 Ensure Bootstrap re-binds modal events
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
var sendCode = function(code)
{
$('.scan').prop('disabled', true);
$('.manually').prop('disabled', true);
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ code +' sent to boxoffice, plase wait…');
$.ajax({
url: `${ApiUrl}scan`,
method: 'POST',
data: {
token: TOKEN,
event_date_id: eventDateId,
order_code: code
},
success: function(result,status,xhr)
{
var apiResult = JSON.parse(result);
if ( apiResult.result )
{
$('#scan-result').removeClass('bg-dark').addClass('bg-success').html(apiResult.message+''+apiResult.seating+''+apiResult.tickets);
// reset input to set next code
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html(apiResult.message);
}
},
error: function(xhr,status,error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ result.text +' could not be sent to boxoffice, please try again');
},
complete: function()
{
$('.scan').prop('disabled', false);
$('.manually').prop('disabled', false);
}
});
}
var scanError = function (error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html("Scanning failed: " + error);
f7App.popup.open('#modal-scan-result');
};
var scanSuccess = function(result)
{
if (! result.cancelled )
{
if (eventDateId > -1)
{
sendCode(result.text);
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('You must select an event date to scan tickets');
}
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Scan was cancelled');
}
f7App.popup.open('#modal-scan-result');
};
$(document).on('click', '.reload-events', function()
{
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {
$('.customer-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
// $('.customer-screen ul.events').append(`
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}
//
//
// `);
$('.customer-screen div.events').append(`
${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}
0/500
`);
// $('.customer-screen ul.events').append(`
//
//
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
// ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} –
// ${val.venue_title} – ${val.venue_full}
//
//
//
//
// `);
// $('.customer-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.'+xhr.statusText+xhr.status, 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});
// load events click
$('.reload-events').trigger('click');
$(document).on('click', '.customer-screen .events .list-group-item', function()
{
$('.customer-screen .events .list-group-item').removeClass('active');
$(this).addClass('active');
$('#scan-info').html($(this).html());
eventId = $(this).attr('data-event-id');
eventDateId = $(this).attr('data-event-date-id');
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
// first scan on event date click
//cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
f7App.popup.open('#modal-scan-result');
});
$(document).on('click', '.scan', function()
{
cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
});
$(document).on('click', '.manually', function()
{
sendCode($('[name="code"]').val());
});
});
// $('ons-button').on('click', function(e) {
// ons.notification.alert('Button is tapped!');
// })
});
}
this is the code
—
### ✅ Confirmed Root Problem:
Cordova on Android (especially on SDK 30+) has stricter policies on external requests from WebView. Your `status: 0` is a **silent fail**, often due to:
– ❌ Content Security Policy (CSP) blocks external requests
– ❌ `cordova-plugin-whitelist` not installed or misconfigured
– ❌ Mixed content (HTTPS app trying HTTP API)
– ❌ New SDK blocking external domains unless explicitly allowed
—
### ✅ SOLUTION CHECKLIST (Step-by-Step)
#### ✅ 1. Make sure `cordova-plugin-whitelist` is installed
Run:
cordova plugin add cordova-plugin-whitelist
—
#### ✅ 2. In `config.xml`, add these:
<!-- Allow all network access -->
<access origin="*" />
<allow-navigation href="*" />
<allow-intent href="*" />
<preference name="AndroidLaunchMode" value="singleTask" />
If your API is `https://staging.fossettscircus.com`, you can also do:
<access origin="https://staging.fossettscircus.com" />
—
#### ✅ 3. Add a **Content Security Policy** meta tag in `index.html`:
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' data: gap: https://staging.fossettscircus.com 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline'; media-src *">
This is crucial or WebView will silently block your AJAX requests.
—
#### ✅ 4. Debug using `adb logcat`
Run this while testing the app:
adb logcat | grep chromium
This shows errors like:
– `Blocked by Content Security Policy`
– `Mixed content blocked`
– `Failed to load resource`
—
#### ✅ 5. Verify Permissions & Internet Access
Make sure `AndroidManifest.xml` has:
<uses-permission android:name="android.permission.INTERNET" />
Without this, no network calls will work on real device.
—
#### ✅ 6. Check for HTTPS issues
If your backend uses a **self-signed certificate** or invalid SSL, WebView **will block** the request.
– Open `https://staging.fossettscircus.com/boxoffice/index.php/api/today` on a mobile browser.
– If there's a certificate error, fix your SSL cert.
– You **cannot bypass SSL warnings in Cordova WebView** without insecure plugins (not recommended).
—
### 💡 Extra: Force Older SDK (For Testing)
If the issue started after SDK update, try forcing Cordova to use SDK 30:
In `config.xml`:
<preference name="android-targetSdkVersion" value="30" />
Then:
cordova platform rm android
cordova platform add android@latest
cordova build android
—
### ✅ Summary Fix Guide
| Step | Fix |
|——|—–|
| ✅ Whitelist plugin | `cordova-plugin-whitelist` |
| ✅ CSP tag | Add correct meta tag in `index.html` |
| ✅ config.xml | Allow `access` and `navigation` |
| ✅ Check HTTPS | Confirm backend cert is valid |
| ✅ logcat | Use `adb logcat` to get real cause |
—
Let me know:
– What SDK version your app is using now?
– If you want me to validate your actual backend endpoint headers?
– If you'd like a pre-built CSP “ and `config.xml` snippet customized for your app.
I'm here to help you get this resolved quickly.
Thenet
You're **almost fully set up**, but a few **critical fixes are missing** that are likely causing your **Cordova Android AJAX requests to fail with status 0** (especially on SDK 30+ or newer WebView versions).
—
### ✅ You Need to Do These 4 Fixes:
—
### ✅ 1. Add the Correct “ to `index.html`
In your `www/index.html`, inside “, add:
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' data: gap: https://staging.fossettscircus.com 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline'; media-src *">
Without this, Android's WebView will silently block your `$.ajax()` request — even if you allow everything in `config.xml`.
—
### ✅ 2. Declare `networkSecurityConfig` for HTTPS and SDK 30+
Create a file: `platforms/android/app/src/main/res/xml/network_security_config.xml`
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
Then in `platforms/android/app/src/main/AndroidManifest.xml`, inside the “ tag:
android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true"
> This is necessary if you're debugging against HTTP or using an SSL certificate that may not be recognized (e.g., staging/self-signed).
—
### ✅ 3. Add Android-specific preferences in `config.xml`
Inside your “ tag (root), add:
<preference name="AndroidXEnabled" value="true" />
<preference name="AndroidInsecureFileModeEnabled" value="true" />
<preference name="android-minSdkVersion" value="22" />
<preference name="android-targetSdkVersion" value="30" />
Adjust `targetSdkVersion` if needed. SDK 31+ can cause issues if your app or plugins aren’t fully compatible.
—
### ✅ 4. Double-Check the `cordova-plugin-whitelist`
Make sure this plugin is **installed**:
cordova plugin add cordova-plugin-whitelist
You’ve added the “ and “ — but **without the plugin, those tags won’t do anything**.
—
### 🔁 OPTIONAL: Clean + Rebuild
After these changes, **remove and re-add the Android platform** to ensure clean rebuild:
cordova platform rm android
cordova platform add android
cordova build android
—
### ✅ Final Checklist Summary:
| 🔧 Fix | Status |
|——-|——–|
| ✅ `cordova-plugin-whitelist` | Required ✔️ |
| ✅ CSP meta in `index.html` | Add ✔️ |
| ✅ `network_security_config.xml` | Add ✔️ |
| ✅ `usesCleartextTraffic` & `networkSecurityConfig` in Manifest | Add ✔️ |
| ✅ SDK Targeting and AndroidX | Add ✔️ |
—
Once these are added, **Cordova will no longer block your AJAX to `https://staging.fossettscircus.com`**, and your customer/staff event list will load as expected.
Let me know if you want me to generate the exact files (`AndroidManifest.xml`, `network_security_config.xml`) or validate SSL from your endpoint!
cordova-plugin-battery-status 1.2.5 "Battery"
cordova-plugin-camera 8.0.0 "Camera"
cordova-plugin-device 1.1.7 "Device"
cordova-plugin-dialogs 1.3.4 "Notification"
cordova-plugin-file 8.1.3 "File"
cordova-plugin-geolocation 5.0.0 "Geolocation"
cordova-plugin-globalization 1.0.9 "Globalization"
cordova-plugin-inappbrowser 1.7.2 "InAppBrowser"
cordova-plugin-media-capture 6.0.0 "Capture"
cordova-plugin-network-information 1.3.4 "Network Information"
cordova-plugin-splashscreen 6.0.1 "Splashscreen"
cordova-plugin-vibration 2.1.6 "Vibration"
phonegap-plugin-barcodescanner 8.1.0 "BarcodeScanner"
—
### ❗ Missing Plugin: `cordova-plugin-whitelist`
This plugin **must be installed** for the “ and AJAX calls to work on Android WebView. Without it, network requests will silently fail — which is exactly what you're experiencing (`status = 0`).
—
### ✅ To Fix This:
Run:
cordova plugin add cordova-plugin-whitelist
Then confirm it’s added by running:
cordova plugin ls
You should see:
cordova-plugin-whitelist 1.3.5 "Whitelist"
—
### 🔁 After Installing:
1. Make sure your `config.xml` contains:
<access origin="*" />
<allow-navigation href="*" />
<allow-intent href="*" />
2. Rebuild the Android app:
cordova platform rm android
cordova platform add android
cordova build android
—
### ✅ Bonus: Test Network from Cordova App
You can confirm it’s working by adding this test in `deviceready`:
fetch('https://staging.fossettscircus.com/boxoffice/index.php/api/today', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'token=fossettscircustoken'
})
.then(res => res.text())
.then(res => console.log('✅ Success:', res))
.catch(err => console.error('❌ Fetch Error:', err));
If this still fails **after adding the whitelist plugin**, then the issue is likely in your **CSP** or **Android WebView config**.
—
Let me know once you add `cordova-plugin-whitelist` — I’ll help you verify and confirm everything is working.
Checking Java JDK and Android SDK versions
ANDROID_HOME=/home/admin1/Android/Sdk (recommended setting)
ANDROID_SDK_ROOT=undefined (DEPRECATED)
Using Android SDK: /home/admin1/Android/Sdk
BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed
Subproject Path: CordovaLib
Subproject Path: app
> Configure project :app
WARNING: Using flatDir should be avoided because it doesn't support any meta-data formats.
> Task :CordovaLib:compileDebugJavaWithJavac
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
> Task :app:compileDebugJavaWithJavac FAILED
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:25: error: cannot find symbol
import org.apache.cordova.Whitelist;
^
symbol: class Whitelist
location: package org.apache.cordova
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:32: error: cannot find symbol
private Whitelist allowedNavigations;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:33: error: cannot find symbol
private Whitelist allowedIntents;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:34: error: cannot find symbol
private Whitelist allowedRequests;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:138: error: cannot find symbol
public Whitelist getAllowedNavigations() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:142: error: cannot find symbol
public void setAllowedNavigations(Whitelist allowedNavigations) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:146: error: cannot find symbol
public Whitelist getAllowedIntents() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:150: error: cannot find symbol
public void setAllowedIntents(Whitelist allowedIntents) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:154: error: cannot find symbol
public Whitelist getAllowedRequests() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:158: error: cannot find symbol
public void setAllowedRequests(Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:41: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:41: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:45: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:45: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:50: error: cannot find symbol
allowedRequests = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:61: error: cannot find symbol
allowedNavigations = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:62: error: cannot find symbol
allowedIntents = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:63: error: cannot find symbol
allowedRequests = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
21 errors
[Incubating] Problems report is available at: file:///home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/build/reports/problems/problems-report.html
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler output below.
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:25: error: cannot find symbol
import org.apache.cordova.Whitelist;
^
symbol: class Whitelist
location: package org.apache.cordova
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:32: error: cannot find symbol
private Whitelist allowedNavigations;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:33: error: cannot find symbol
private Whitelist allowedIntents;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:34: error: cannot find symbol
private Whitelist allowedRequests;
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:48: error: cannot find symbol
public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:138: error: cannot find symbol
public Whitelist getAllowedNavigations() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:142: error: cannot find symbol
public void setAllowedNavigations(Whitelist allowedNavigations) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:146: error: cannot find symbol
public Whitelist getAllowedIntents() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:150: error: cannot find symbol
public void setAllowedIntents(Whitelist allowedIntents) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:154: error: cannot find symbol
public Whitelist getAllowedRequests() {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:158: error: cannot find symbol
public void setAllowedRequests(Whitelist allowedRequests) {
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:41: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:41: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:45: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:45: error: cannot find symbol
this(new Whitelist(), new Whitelist(), null);
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:50: error: cannot find symbol
allowedRequests = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:61: error: cannot find symbol
allowedNavigations = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:62: error: cannot find symbol
allowedIntents = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
/home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java:63: error: cannot find symbol
allowedRequests = new Whitelist();
^
symbol: class Whitelist
location: class WhitelistPlugin
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
21 errors
* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with –scan to get full insights.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '–warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.13/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD FAILED in 9s
31 actionable tasks: 31 executed
Command failed with exit code 1: /home/admin1/nethues-projects/Klassenergy-project/android-apps/circusscanner/platforms/android/tools/gradlew cdvBuildDebug
—
## ❌ Problem:
You're using the `cordova-plugin-whitelist`, but it's **failing to compile** because:
error: cannot find symbol class Whitelist
> This means that the `Whitelist.java` class from Cordova core **no longer exists** in newer versions (Cordova Android 11+).
This is a **known issue** caused by:
– Adding `cordova-plugin-whitelist` on a Cordova project that uses **modern Android platform (cordova-android 11+)**
– The whitelist logic is now **built-in**, and **you no longer need this plugin**
—
## ✅ Solution: Remove the plugin (no longer required)
You should **remove the `cordova-plugin-whitelist`** completely and just configure permissions via `config.xml`.
### 🧹 Run this:
cordova plugin rm cordova-plugin-whitelist
Then **verify it's gone**:
cordova plugin ls
—
## ✅ Then Rebuild:
cordova platform rm android
cordova platform add android@latest
cordova build android
This will remove the incompatible references to the missing `Whitelist` class and clean your Android build.
—
## ✅ You STILL Need CSP + Access Rules
Even though the plugin is removed, **you must keep the config.xml and CSP setup** like this:
### ✅ In `config.xml`
<access origin="*" />
<allow-navigation href="*" />
<allow-intent href="*" />
### ✅ In `index.html` “
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' data: gap: https://staging.fossettscircus.com 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline'; media-src *">
—
## ✅ Summary of Actions
| Step | Action |
|——|——–|
| 🔧 1 | Remove `cordova-plugin-whitelist` (not needed in cordova-android 11+) |
| 🔧 2 | Use “ and CSP rules instead |
| 🔧 3 | Clean platform and rebuild |
| 🔧 4 | Keep CSP + allow-navigation in place |
—
Let me know if you'd like me to review your full `index.html` head or generate a minimal working setup. Once rebuilt, your AJAX calls from Cordova should start working normally on Android again.
—
## ✅ Option 1: Use `chrome://inspect` (Best for Cordova/WebView debugging)
### 📱 Steps:
1. **Run your Cordova app** on the emulator using:
cordova run android --emulator
2. **Open Google Chrome** on your PC.
3. In the address bar, go to:
chrome://inspect
4. Under **Remote Target**, your emulator's WebView will show up (e.g., `com.fossettscircus.scanner`).
5. Click **“inspect”** — DevTools will open.
6. Now you can:
– See **console.log** output
– See **network requests** (your AJAX calls)
– View **errors and exceptions**
– Debug your app just like a webpage
> 💡 If you don’t see anything, make sure **Developer options > USB Debugging** is enabled in the emulator.
—
## ✅ Option 2: Use `adb logcat` for full device logs
1. Open Terminal or Android Studio **Terminal tab**.
2. Run:
adb logcat | grep chromium
or to see general logs:
adb logcat
3. Look for logs like:
I/chromium: [INFO:CONSOLE(12)] "Something went wrong", source: ...
This helps track:
– AJAX errors
– Mixed content issues
– CORS policy violations
– JavaScript syntax problems
—
## ✅ Option 3: Log Directly in App
Use `console.log` and `alert` during development:
error: function(xhr, status, error) {
console.log("AJAX failed:", xhr, status, error);
alert("Error: " + xhr.status + " " + error);
}
—
### 🔁 Pro Tip (Optional): Enable Full WebView Debugging in Cordova
If not already done, in `config.xml` add:
<preference name="WebViewBounce" value="false" />
<preference name="AndroidWebViewDebuggingEnabled" value="true" />
—
Let me know if you're using a **physical device** instead — steps are slightly different.
if (cordova.platformId === 'android') {
var permissions = cordova.plugins.permissions;
permissions.checkPermission(permissions.CAMERA, function (status) {
if (!status.hasPermission) {
// Request permission
permissions.requestPermission(
permissions.CAMERA,
function (status) {
if (status.hasPermission) {
navigator.splashscreen.hide(); // Hide splash after permission
initializeApp(); // Proceed with your app
} else {
navigator.app.exitApp(); // Exit if denied
}
},
function () {
navigator.app.exitApp(); // Exit on request error
}
);
} else {
navigator.splashscreen.hide();
initializeApp(); // Permission already granted
}
});
} else {
navigator.splashscreen.hide(); // For browser/iOS fallback
let TOKEN = 'fossettscircustoken';
var eventId = -1;
var eventDateId = -1;
let ApiUrl = 'https://staging.fossettscircus.com/boxoffice/index.php/api/';
var scanConfig = {
preferFrontCamera : false, // iOS and Android
showFlipCameraButton : true, // iOS and Android
showTorchButton : true, // iOS and Android
torchOn: false, // Android, launch with the torch switched on (if available)
saveHistory: false, // Android, save scan history (default false)
prompt : "Place a code inside the scan area", // Android
resultDisplayDuration: 500, // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500
formats : "QR_CODE", // default: all but PDF_417 and RSS_EXPANDED
//orientation : "landscape", // Android only (portrait|landscape), default unset so it rotates with the device
disableAnimations : true, // iOS
disableSuccessBeep: false // iOS and Android
};
$(document).ready(function()
{
$(document).on('page:init', '.page[data-name="home"]', function () {
});
$(document).on('page:init', function () {
$(document).on('click', '.logout-staff', function()
{
localStorage.removeItem('staff_token');
localStorage.removeItem('access_type');
f7App.views.main.router.navigate('/');
});
});
$(document).on('page:init', '.page[data-name="staff-pay-terminal"]', function () {
$(document).on('input', '#amountInput', function () {
const amount = parseFloat($(this).val());
const btn = $('#chargeBtn');
if (amount > 0) {
btn.removeClass('disabled color-gray').addClass('color-green');
btn.text('Charge €' + amount.toFixed(2));
} else {
btn.addClass('disabled color-gray').removeClass('color-green');
btn.text('Charge €0.00');
}
});
})
var staffEventsLoaded = false;
$(document).on('page:init', '.page[data-name="staff-tickets"]', function () {
$(document).on('click', '.reload-events-staff', function()
{
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {
$('.staff-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
$('.staff-screen div.events').append(`
${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}
0/500
`);
//$('.staff-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}Collect Payment`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
});
// load events click
$('.reload-events-staff').trigger('click');
});
$(document).on('page:init', '.page[data-name="staff-check-orders"]', function () {
});
$(document).on('page:init', '.page[data-name="staff-dashboard"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-tickets').on('click', function () {
f7App.views.main.router.navigate('/staff-tickets/');
});
$('#open-pay-terminal').on('click', function () {
f7App.views.main.router.navigate('/staff-pay-terminal/');
});
$('#check-orders').on('click', function () {
f7App.views.main.router.navigate('/staff-check-orders/');
});
// load events click
$('.reload-events-staff').trigger('click');
});
$(document).on('page:init', '.page[data-name="staff-login"]', function () {
$('.back-to-access').on('click', function () {
f7App.views.main.router.navigate('/');
});
$('#staff-login-form').on('submit', function (e) {
e.preventDefault();
var email = $('#staff-email').val();
var password = $('#staff-password').val();
f7App.dialog.preloader('Logging in…');
$.ajax({
url: `${ApiUrl}staff_login`,
method: 'POST',
data: {
token: TOKEN,
email: email,
password: password
},
success: function (result, status, xhr) {
var apiResult = JSON.parse(result);
if (apiResult.result) {
f7App.views.main.router.navigate('/staff/');
} else {
$('#login-result').html(apiResult.message);
}
},
error: function (xhr, status, error) {
f7App.dialog.alert('Something went wrong. Please try again.', 'Error');
},
complete: function () {
// ✅ Hide preloader after AJAX completes
f7App.dialog.close();
}
});
});
});
// Page: Customer
$(document).on('page:init', '.page[data-name="customer"]', function () {
// 👇 Ensure Bootstrap re-binds modal events
var sendCode = function(code)
{
$('.scan').prop('disabled', true);
$('.manually').prop('disabled', true);
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ code +' sent to boxoffice, plase wait…');
$.ajax({
url: `${ApiUrl}scan`,
method: 'POST',
data: {
token: TOKEN,
event_date_id: eventDateId,
order_code: code
},
success: function(result,status,xhr)
{
var apiResult = JSON.parse(result);
if ( apiResult.result )
{
$('#scan-result').removeClass('bg-dark').addClass('bg-success').html(apiResult.message+''+apiResult.seating+''+apiResult.tickets);
// reset input to set next code
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html(apiResult.message);
}
},
error: function(xhr,status,error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Code '+ result.text +' could not be sent to boxoffice, please try again');
},
complete: function()
{
$('.scan').prop('disabled', false);
$('.manually').prop('disabled', false);
}
});
}
var scanError = function (error)
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html("Scanning failed: " + error);
f7App.popup.open('#modal-scan-result');
};
var scanSuccess = function(result)
{
if (! result.cancelled )
{
if (eventDateId > -1)
{
sendCode(result.text);
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('You must select an event date to scan tickets');
}
}
else
{
$('#scan-result').removeClass('bg-success').addClass('bg-dark').html('Scan was cancelled');
}
f7App.popup.open('#modal-scan-result');
};
loadEvent(ApiUrl);
$(document).on('click', '.reload-events', function()
{
loadEvent(ApiUrl);
});
// load events click
//$('.reload-events').trigger('click');
$(document).on('click', '.customer-screen .events .list-group-item', function()
{
$('.customer-screen .events .list-group-item').removeClass('active');
$(this).addClass('active');
$('#scan-info').html($(this).html());
eventId = $(this).attr('data-event-id');
eventDateId = $(this).attr('data-event-date-id');
$('[name="code"]').val(eventId +'.'+ eventDateId +'.');
// first scan on event date click
//cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
f7App.popup.open('#modal-scan-result');
});
$(document).on('click', '.scan', function()
{
cordova.plugins.barcodeScanner.scan(scanSuccess, scanError, scanConfig);
});
$(document).on('click', '.manually', function()
{
sendCode($('[name="code"]').val());
});
});
// $('ons-button').on('click', function(e) {
// ons.notification.alert('Button is tapped!');
// })
});
}
}, false);
function loadEvent(ApiUrl)
{
f7App.dialog.preloader('Loading events…');
$.ajax({
url: `${ApiUrl}today`,
method: 'POST',
data: {
token: TOKEN
},
success: function(result,status,xhr)
{
console.log(result);
var events = JSON.parse(result);
if (events.result) {
$('.customer-screen ul.events').html('');
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
$.each(events.data, function(i, val)
{
var eventDatetime = new Date(val.event_datetime);
var dateOptions = { year: '2-digit', month: '2-digit', day: '2-digit' };
var timeOptions = { hour12: true, hour: '2-digit', minute: '2-digit' };
var dayname=weekday[eventDatetime.getDay()];
// $('.customer-screen ul.events').append(`
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}
//
//
// `);
$('.customer-screen div.events').append(`
${val.venue_full}
${dayname} at ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
${eventDatetime.toLocaleTimeString('en-US', timeOptions)}
0/500
`);
// $('.customer-screen ul.events').append(`
//
//
//
//
// ${eventDatetime.toLocaleDateString('en-GB', dateOptions)} –
// ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} –
// ${val.venue_title} – ${val.venue_full}
//
//
//
//
// `);
// $('.customer-screen ul.events').append(`${eventDatetime.toLocaleDateString('en-GB', dateOptions)} – ${eventDatetime.toLocaleTimeString('en-US', timeOptions)} ${dayname} – ${val.venue_title} – ${val.venue_full}`);
});
}else{
$('.events').html(`${events.message}`);
}
},
error: function(xhr,status,error)
{
f7App.dialog.alert('Something went wrong. Please try again.'+xhr.statusText+xhr.status, 'Error');
},
complete: function()
{
f7App.dialog.close();
}
});
}
loadEvent call not working in android
> ❌ Your `loadEvent(ApiUrl)` function **is not working on Android**, but works in the browser. This happens because `TOKEN` is undefined in that context.
—
## ✅ Root Cause
Inside your `deviceready` block, you declared `TOKEN` like this:
let TOKEN = 'fossettscircustoken';
But your `loadEvent(ApiUrl)` function is **defined outside** that block.
So in Android builds (strict JavaScript scope), `TOKEN` is **not accessible globally**, and becomes **`undefined` inside `loadEvent()`**, which leads to:
– A broken AJAX request
– Possibly a `status: 0` error or blank response
– The request not being sent at all
—
## ✅ Fix It – Move or Redefine `TOKEN` at the Right Scope
### ✅ Option 1: Move `loadEvent` *inside* `deviceready`
**Preferred for clarity:**
Move this function just **before the line**:
$(document).on('page:init', '.page[data-name="customer"]', function () {
So it shares the same scope as your `TOKEN` and `ApiUrl`.
—
### ✅ Option 2: Declare TOKEN at the **global level**
Instead of:
let TOKEN = 'fossettscircustoken';
Change it to:
window.TOKEN = 'fossettscircustoken';
Now in `loadEvent()`, `TOKEN` will always be accessible globally.
✅ This is the easiest patch for now.
—
### ✅ Also: Check Chrome Debug or Log Output
If you're running in Android Emulator or Device, use:
adb logcat | grep chromium
Or open `chrome://inspect` in Chrome to see WebView console.
You might find:
Uncaught ReferenceError: TOKEN is not defined
—
### ✅ Confirm with a Simple Alert (for testing)
Add this to the first line of `loadEvent()`:
alert("TOKEN: " + TOKEN); // will show undefined if broken
If alert says `undefined`, then that proves the scope issue.
—
## ✅ Summary
| Issue | Fix |
|——-|—–|
| `TOKEN` undefined inside `loadEvent()` | Make it global or move function inside `deviceready` |
| Scope mismatch | Don't use `let TOKEN` inside isolated blocks unless shared scope |
| Silent AJAX failure in Android | Caused by `undefined` token, not network |
—
Let me know if you want a full restructured version of the file with corrected scope and refactored flow.