Skip to content

Commit 92fce52

Browse files
Merge pull request #12 from virtual-labs/dev
Automated update - exp-converting-regular-expression-iiith
2 parents 27901c4 + 6060ca1 commit 92fce52

File tree

1 file changed

+288
-0
lines changed

1 file changed

+288
-0
lines changed
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
// Mobile Detection and Overlay Script
2+
// This script detects mobile devices and shows a desktop optimization warning
3+
4+
class MobileDetection {
5+
constructor() {
6+
this.isMobile = this.detectMobile();
7+
this.overlayShown = false;
8+
this.init();
9+
}
10+
11+
detectMobile() {
12+
// Check for mobile user agents
13+
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
14+
15+
// Mobile device patterns
16+
const mobilePatterns = [
17+
/Android/i,
18+
/webOS/i,
19+
/iPhone/i,
20+
/iPad/i,
21+
/iPod/i,
22+
/BlackBerry/i,
23+
/Windows Phone/i,
24+
/Opera Mini/i,
25+
/IEMobile/i,
26+
/Mobile/i
27+
];
28+
29+
// Check screen size (additional check for small screens)
30+
const isSmallScreen = window.innerWidth <= 768 || window.innerHeight <= 600;
31+
32+
// Check touch capability
33+
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
34+
35+
// Return true if any mobile pattern matches OR if it's a small touch screen
36+
return mobilePatterns.some(pattern => pattern.test(userAgent)) ||
37+
(isSmallScreen && isTouchDevice);
38+
}
39+
40+
init() {
41+
if (this.isMobile && !this.overlayShown) {
42+
// Wait for DOM to be ready
43+
if (document.readyState === 'loading') {
44+
document.addEventListener('DOMContentLoaded', () => this.showOverlay());
45+
} else {
46+
this.showOverlay();
47+
}
48+
}
49+
}
50+
51+
showOverlay() {
52+
if (this.overlayShown) return;
53+
54+
this.overlayShown = true;
55+
56+
// Create overlay HTML
57+
const overlay = document.createElement('div');
58+
overlay.id = 'mobile-warning-overlay';
59+
overlay.innerHTML = `
60+
<div class="mobile-overlay-backdrop">
61+
<div class="mobile-overlay-content">
62+
<div class="mobile-overlay-icon">
63+
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
64+
<path d="M12 2L2 7V10C2 16 6 20.5 12 22C18 20.5 22 16 22 10V7L12 2Z" stroke="#f59e0b" stroke-width="2" fill="#fef3c7"/>
65+
<path d="M12 8V13M12 16H12.01" stroke="#f59e0b" stroke-width="2" stroke-linecap="round"/>
66+
</svg>
67+
</div>
68+
<h2 class="mobile-overlay-title">Desktop Experience Recommended</h2>
69+
<p class="mobile-overlay-description">
70+
This discrete mathematics experiment is optimized for desktop computers with larger screens and mouse interaction.
71+
While you can continue on mobile, you may experience:
72+
</p>
73+
<ul class="mobile-overlay-list">
74+
<li>• Difficulty interacting with complex visualizations</li>
75+
<li>• Limited screen space for mathematical content</li>
76+
<li>• Reduced functionality for graph manipulations</li>
77+
<li>• Suboptimal user experience</li>
78+
</ul>
79+
<div class="mobile-overlay-actions">
80+
<button class="mobile-overlay-btn mobile-overlay-btn-primary" onclick="mobileDetection.continueAnyway()">
81+
Continue Anyway
82+
</button>
83+
<button class="mobile-overlay-btn mobile-overlay-btn-secondary" onclick="mobileDetection.goBack()">
84+
Use Desktop Instead
85+
</button>
86+
</div>
87+
<p class="mobile-overlay-footer">
88+
For the best learning experience, please access this on a desktop or laptop computer.
89+
</p>
90+
</div>
91+
</div>
92+
`;
93+
94+
// Add overlay styles
95+
const styles = `
96+
<style>
97+
.mobile-overlay-backdrop {
98+
position: fixed;
99+
top: 0;
100+
left: 0;
101+
right: 0;
102+
bottom: 0;
103+
background: rgba(0, 0, 0, 0.8);
104+
backdrop-filter: blur(4px);
105+
z-index: 10000;
106+
display: flex;
107+
align-items: center;
108+
justify-content: center;
109+
padding: 20px;
110+
animation: fadeIn 0.3s ease-out;
111+
}
112+
113+
.mobile-overlay-content {
114+
background: white;
115+
border-radius: 16px;
116+
padding: 24px;
117+
max-width: 400px;
118+
width: 100%;
119+
max-height: 90vh;
120+
overflow-y: auto;
121+
text-align: center;
122+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
123+
animation: slideUp 0.3s ease-out;
124+
}
125+
126+
.mobile-overlay-icon {
127+
margin: 0 auto 16px;
128+
width: 48px;
129+
height: 48px;
130+
}
131+
132+
.mobile-overlay-title {
133+
font-size: 20px;
134+
font-weight: 600;
135+
color: #1f2937;
136+
margin-bottom: 12px;
137+
line-height: 1.3;
138+
}
139+
140+
.mobile-overlay-description {
141+
font-size: 14px;
142+
color: #6b7280;
143+
margin-bottom: 16px;
144+
line-height: 1.5;
145+
text-align: left;
146+
}
147+
148+
.mobile-overlay-list {
149+
text-align: left;
150+
font-size: 14px;
151+
color: #6b7280;
152+
margin-bottom: 20px;
153+
padding-left: 0;
154+
list-style: none;
155+
}
156+
157+
.mobile-overlay-list li {
158+
margin-bottom: 6px;
159+
line-height: 1.4;
160+
}
161+
162+
.mobile-overlay-actions {
163+
display: flex;
164+
flex-direction: column;
165+
gap: 12px;
166+
margin-bottom: 16px;
167+
}
168+
169+
.mobile-overlay-btn {
170+
padding: 12px 20px;
171+
border-radius: 8px;
172+
font-size: 14px;
173+
font-weight: 500;
174+
border: none;
175+
cursor: pointer;
176+
transition: all 0.2s ease;
177+
width: 100%;
178+
}
179+
180+
.mobile-overlay-btn-primary {
181+
background: #3b82f6;
182+
color: white;
183+
}
184+
185+
.mobile-overlay-btn-primary:hover {
186+
background: #2563eb;
187+
transform: translateY(-1px);
188+
}
189+
190+
.mobile-overlay-btn-secondary {
191+
background: #f3f4f6;
192+
color: #374151;
193+
border: 1px solid #d1d5db;
194+
}
195+
196+
.mobile-overlay-btn-secondary:hover {
197+
background: #e5e7eb;
198+
transform: translateY(-1px);
199+
}
200+
201+
.mobile-overlay-footer {
202+
font-size: 12px;
203+
color: #9ca3af;
204+
line-height: 1.4;
205+
}
206+
207+
@keyframes fadeIn {
208+
from { opacity: 0; }
209+
to { opacity: 1; }
210+
}
211+
212+
@keyframes slideUp {
213+
from {
214+
opacity: 0;
215+
transform: translateY(20px) scale(0.95);
216+
}
217+
to {
218+
opacity: 1;
219+
transform: translateY(0) scale(1);
220+
}
221+
}
222+
223+
@media (min-width: 480px) {
224+
.mobile-overlay-actions {
225+
flex-direction: row;
226+
}
227+
228+
.mobile-overlay-btn {
229+
width: auto;
230+
flex: 1;
231+
}
232+
}
233+
</style>
234+
`;
235+
236+
// Add styles to head
237+
document.head.insertAdjacentHTML('beforeend', styles);
238+
239+
// Add overlay to body
240+
document.body.appendChild(overlay);
241+
242+
// Prevent body scrolling
243+
document.body.style.overflow = 'hidden';
244+
}
245+
246+
continueAnyway() {
247+
this.hideOverlay();
248+
}
249+
250+
goBack() {
251+
// Try to go back in history, or redirect to a homepage if available
252+
if (window.history.length > 1) {
253+
window.history.back();
254+
} else {
255+
// You can customize this to redirect to your main page
256+
alert('Please bookmark this page and open it on a desktop computer for the best experience.');
257+
}
258+
}
259+
260+
hideOverlay() {
261+
const overlay = document.getElementById('mobile-warning-overlay');
262+
if (overlay) {
263+
overlay.style.animation = 'fadeOut 0.3s ease-out forwards';
264+
setTimeout(() => {
265+
overlay.remove();
266+
document.body.style.overflow = '';
267+
}, 300);
268+
}
269+
}
270+
}
271+
272+
// Add fadeOut animation
273+
document.head.insertAdjacentHTML('beforeend', `
274+
<style>
275+
@keyframes fadeOut {
276+
from { opacity: 1; }
277+
to { opacity: 0; }
278+
}
279+
</style>
280+
`);
281+
282+
// Initialize mobile detection
283+
const mobileDetection = new MobileDetection();
284+
285+
// Export for use in other scripts if needed
286+
if (typeof module !== 'undefined' && module.exports) {
287+
module.exports = MobileDetection;
288+
}

0 commit comments

Comments
 (0)