chrissoria Claude Sonnet 4.5 commited on
Commit
cdfa223
·
1 Parent(s): 6924d73

Solution 5: JavaScript override of mobile detection + manual tab switching

Browse files

- Override navigator.maxTouchPoints and platform to fake desktop
- Manually implement tab panel showing/hiding via JavaScript
- Intercept tab clicks and control display with CSS display property
- Bypasses Gradio's broken mobile tab handling completely

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +60 -27
app.py CHANGED
@@ -1281,6 +1281,18 @@ custom_css = """
1281
 
1282
  custom_js = """
1283
  function() {
 
 
 
 
 
 
 
 
 
 
 
 
1284
  // Add click-to-expand functionality for the plot
1285
  document.addEventListener('click', function(e) {
1286
  const plot = e.target.closest('.expandable-plot');
@@ -1299,41 +1311,62 @@ function() {
1299
  }
1300
  });
1301
 
1302
- // Fix mobile tab clicks - comprehensive touch handling
1303
- function fixMobileTabs() {
1304
  const tabs = document.querySelectorAll('[role="tab"]');
1305
- tabs.forEach(tab => {
1306
- // Clear all existing listeners
 
 
 
 
1307
  const newTab = tab.cloneNode(true);
1308
  tab.parentNode.replaceChild(newTab, tab);
1309
 
1310
- // Add multiple event types for better mobile support
1311
- ['touchstart', 'touchend', 'click'].forEach(eventType => {
1312
- newTab.addEventListener(eventType, function(e) {
1313
- if (eventType === 'touchend') {
1314
- e.preventDefault();
1315
- e.stopPropagation();
1316
- // Force focus and click
1317
- this.focus();
1318
- // Dispatch a synthetic mouse click
1319
- const clickEvent = new MouseEvent('click', {
1320
- bubbles: true,
1321
- cancelable: true,
1322
- view: window
1323
- });
1324
- this.dispatchEvent(clickEvent);
1325
- }
1326
- }, { passive: eventType !== 'touchend' });
1327
- });
 
 
 
 
 
 
 
 
 
1328
  });
 
 
 
 
 
 
 
1329
  }
1330
 
1331
- // Run on load and keep monitoring
1332
- setTimeout(fixMobileTabs, 100);
1333
- setTimeout(fixMobileTabs, 500);
1334
- setTimeout(fixMobileTabs, 1000);
 
1335
  const observer = new MutationObserver(() => {
1336
- setTimeout(fixMobileTabs, 50);
1337
  });
1338
  observer.observe(document.body, { childList: true, subtree: true });
1339
  }
 
1281
 
1282
  custom_js = """
1283
  function() {
1284
+ // Force desktop mode - override mobile detection
1285
+ Object.defineProperty(navigator, 'maxTouchPoints', {
1286
+ get: () => 0
1287
+ });
1288
+
1289
+ // Override platform if needed
1290
+ try {
1291
+ Object.defineProperty(navigator, 'platform', {
1292
+ get: () => 'MacIntel'
1293
+ });
1294
+ } catch(e) {}
1295
+
1296
  // Add click-to-expand functionality for the plot
1297
  document.addEventListener('click', function(e) {
1298
  const plot = e.target.closest('.expandable-plot');
 
1311
  }
1312
  });
1313
 
1314
+ // Aggressive tab fixing - manually control tab panels
1315
+ function forceTabSwitching() {
1316
  const tabs = document.querySelectorAll('[role="tab"]');
1317
+ const tabPanels = document.querySelectorAll('[role="tabpanel"]');
1318
+
1319
+ if (tabs.length === 0 || tabPanels.length === 0) return;
1320
+
1321
+ tabs.forEach((tab, index) => {
1322
+ // Remove old listeners by cloning
1323
  const newTab = tab.cloneNode(true);
1324
  tab.parentNode.replaceChild(newTab, tab);
1325
 
1326
+ // Add new click handler that manually shows/hides panels
1327
+ newTab.addEventListener('click', function(e) {
1328
+ e.preventDefault();
1329
+ e.stopPropagation();
1330
+
1331
+ // Hide all panels
1332
+ tabPanels.forEach(panel => {
1333
+ panel.style.display = 'none';
1334
+ panel.setAttribute('aria-hidden', 'true');
1335
+ });
1336
+
1337
+ // Remove selected from all tabs
1338
+ tabs.forEach(t => {
1339
+ t.setAttribute('aria-selected', 'false');
1340
+ t.classList.remove('selected');
1341
+ });
1342
+
1343
+ // Show clicked tab's panel
1344
+ if (tabPanels[index]) {
1345
+ tabPanels[index].style.display = 'block';
1346
+ tabPanels[index].setAttribute('aria-hidden', 'false');
1347
+ }
1348
+
1349
+ // Mark clicked tab as selected
1350
+ this.setAttribute('aria-selected', 'true');
1351
+ this.classList.add('selected');
1352
+ }, true);
1353
  });
1354
+
1355
+ // Ensure first tab is initially selected
1356
+ if (tabPanels.length > 0) {
1357
+ tabPanels.forEach((panel, i) => {
1358
+ panel.style.display = i === 0 ? 'block' : 'none';
1359
+ });
1360
+ }
1361
  }
1362
 
1363
+ // Run tab fixing multiple times
1364
+ setTimeout(forceTabSwitching, 200);
1365
+ setTimeout(forceTabSwitching, 800);
1366
+ setTimeout(forceTabSwitching, 1500);
1367
+
1368
  const observer = new MutationObserver(() => {
1369
+ setTimeout(forceTabSwitching, 100);
1370
  });
1371
  observer.observe(document.body, { childList: true, subtree: true });
1372
  }