Subham9126 commited on
Commit
d269d99
·
verified ·
1 Parent(s): 554dd97

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +592 -97
index.html CHANGED
@@ -1,122 +1,617 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
-
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Dynamic Facet Explorer</title>
8
- <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
9
  <style>
10
- .sticky-query {
11
- position: sticky;
12
- top: 0;
13
- z-Coeff: 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  background-color: white;
15
- padding: 1rem;
16
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
17
- animation: zoomIn 0.5s ease-out;
18
- }
19
- .fade-in {
20
- animation: fadeIn 0.5s ease-out;
21
- @keyframes fadeIn {
22
- 0% {
23
- opacity: 0;
24
- }
25
- 100% {
26
- opacity: 1;
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
  }
30
  </style>
31
  </head>
32
-
33
- <body class="bg-gray-50 min-h-screen font-sans text-gray-800">
34
- <div class="container mx-auto px-4 py-12">
35
-
36
- <!-- Query Input -->
37
- <div class="sticky-query bg-white rounded-lg shadow-lg p-8 mb-12">
38
- <div class="mb-6">
39
- <label for="query" class="block text-lg font-medium text-gray-700 mb-2">Query</label>
40
- <input type="text" id="query" placeholder="Enter your query" class="w-full px-4 py-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
41
- </div>
42
  </div>
43
-
44
- <!-- Section 1: Input -->
45
- <div class="bg-white rounded-lg shadow-lg p-8 mb-12">
46
- <div class="mb-6">
47
- <label for="given_facet" class="block text-lg font-medium text-gray-700 mb-2">Given Facet</label>
48
- <input type="text" id="given_facet" placeholder="Enter your facet in Python dictionary format" class="w-full px-4 py-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
49
- </div>
50
- <button id="submit" class="w-full bg-blue-600 text-white py-3 px-6 rounded-md hover:bg-blue-700 transition duration-300 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">Submit</button>
51
  </div>
52
-
53
- <!-- Section 2: Dynamic Boxes -->
54
- <div id="dynamicBoxes" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"></div>
55
-
56
- <!-- Get List Button -->
57
- <div class="mt-12 text-center">
58
- <button id="getList" class="bg-green-600 text-white py-3 px-8 rounded-md hover:bg-green-700 transition duration-300 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2">Get List</button>
59
- <button id="reset" class="bg-red-600 text-white py-3 px-8 ml-4 rounded-md hover:bg-red-700 transition duration-300 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">Reset</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  </div>
61
-
62
- <!-- Result Display -->
63
- <div id="result" class="mt-12 text-center text-2xl font-semibold"></div>
64
  </div>
65
-
66
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
67
  <script>
68
- $(document).ready(function() {
69
- let isResultShown = false;
70
- $('#submit').click(function() {
71
- const query = $('#query').val();
72
- const givenFacet = $('#given_facet').val();
73
- try {
74
- const facetObj = eval('(' + givenFacet + ')');
75
- generateBoxes(facetObj);
76
- resetResult();
77
- } catch (error) {
78
- alert('Invalid facet format. Please enter a valid Python dictionary.');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  });
81
- function generateBoxes(facetObj) {
82
- const $dynamicBoxes = $('#dynamicBoxes').empty();
83
- Object.entries(facetObj).forEach(([key, values]) => {
84
- const $box = $('<div>').addClass('bg-white rounded-lg shadow-md p-6 fade-in');
85
- const $title = $('<div>').addClass('flex items-center justify-between mb-4')
86
- .append($('<h2>').addClass('text-xl font-semibold').text(`'${key}'`))
87
- .append($('<input>').attr({
88
- type: 'checkbox',
89
- name: key,
90
- class: 'form-checkbox h-5 w-5 text-blue-600'
91
- }));
92
- const $content = $('<div>').addClass('space-y-2');
93
- values.forEach(value => {
94
- $content.append($('<p>').addClass('text-gray-600').text(value));
95
- });
96
- $box.append($title).append($content);
97
- $dynamicBoxes.append($box);
98
  });
99
  }
100
- $('#getList').click(function() {
101
- const checkedBoxes = $('input[type="checkbox"]:checked').map(function() {
102
- return `'${this.name}'`;
103
- }).get();
104
- const result = `[${checkedBoxes.join(', ')}]`;
105
- $('#result').text(result).addClass('fade-in');
106
- isResultShown = true;
107
- });
108
- $('#reset').click(function() {
109
- $('input[type="checkbox"]').prop('checked', false);
110
- if (isResultShown) {
111
- $('#result').text('').removeClass('fade-in');
112
- isResultShown = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  }
114
- });
115
- function resetResult() {
116
- $('#result').text('').removeClass('fade-in');
117
- isResultShown = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
  });
 
 
 
120
  </script>
121
  </body>
122
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Video Player</title>
 
7
  <style>
8
+ * {
9
+ box-sizing: border-box;
10
+ margin: 0;
11
+ padding: 0;
12
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
13
+ }
14
+
15
+ body {
16
+ background-color: #f5f5f5;
17
+ color: #333;
18
+ line-height: 1.6;
19
+ }
20
+
21
+ .container {
22
+ max-width: 1200px;
23
+ margin: 0 auto;
24
+ padding: 20px;
25
+ }
26
+
27
+ header {
28
+ background-color: #2c3e50;
29
+ color: white;
30
+ padding: 20px 0;
31
+ text-align: center;
32
+ margin-bottom: 30px;
33
+ border-radius: 5px;
34
+ }
35
+
36
+ h1 {
37
+ font-size: 2.5rem;
38
+ }
39
+
40
+ .search-container {
41
+ margin: 20px 0;
42
+ display: flex;
43
+ justify-content: center;
44
+ }
45
+
46
+ #search {
47
+ width: 70%;
48
+ padding: 12px;
49
+ border: 1px solid #ddd;
50
+ border-radius: 25px;
51
+ font-size: 16px;
52
+ outline: none;
53
+ transition: all 0.3s;
54
+ }
55
+
56
+ #search:focus {
57
+ border-color: #3498db;
58
+ box-shadow: 0 0 8px rgba(52, 152, 219, 0.5);
59
+ }
60
+
61
+ .video-list {
62
+ display: grid;
63
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
64
+ gap: 20px;
65
+ margin-bottom: 30px;
66
+ }
67
+
68
+ .video-item {
69
  background-color: white;
70
+ border-radius: 8px;
71
+ overflow: hidden;
72
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
73
+ transition: transform 0.3s, box-shadow 0.3s;
74
+ cursor: pointer;
75
+ }
76
+
77
+ .video-item:hover {
78
+ transform: translateY(-5px);
79
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
80
+ }
81
+
82
+ .video-thumbnail {
83
+ position: relative;
84
+ padding-top: 56.25%; /* 16:9 aspect ratio */
85
+ background-color: #000;
86
+ }
87
+
88
+ .video-thumbnail img {
89
+ position: absolute;
90
+ top: 0;
91
+ left: 0;
92
+ width: 100%;
93
+ height: 100%;
94
+ object-fit: cover;
95
+ }
96
+
97
+ .video-info {
98
+ padding: 15px;
99
+ }
100
+
101
+ .video-title {
102
+ font-size: 1.1rem;
103
+ margin-bottom: 5px;
104
+ font-weight: 600;
105
+ display: -webkit-box;
106
+ -webkit-line-clamp: 2;
107
+ -webkit-box-orient: vertical;
108
+ overflow: hidden;
109
+ }
110
+
111
+ .video-player-container {
112
+ position: fixed;
113
+ top: 0;
114
+ left: 0;
115
+ width: 100%;
116
+ height: 100%;
117
+ background-color: rgba(0, 0, 0, 0.9);
118
+ display: flex;
119
+ flex-direction: column;
120
+ justify-content: center;
121
+ align-items: center;
122
+ z-index: 1000;
123
+ opacity: 0;
124
+ pointer-events: none;
125
+ transition: opacity 0.3s;
126
+ }
127
+
128
+ .video-player-container.show {
129
+ opacity: 1;
130
+ pointer-events: all;
131
+ }
132
+
133
+ .video-player-wrapper {
134
+ width: 90%;
135
+ max-width: 1000px;
136
+ position: relative;
137
+ }
138
+
139
+ #videoPlayer {
140
+ width: 100%;
141
+ border-radius: 8px;
142
+ background-color: #000;
143
+ }
144
+
145
+ .player-controls {
146
+ display: flex;
147
+ justify-content: space-between;
148
+ align-items: center;
149
+ background-color: rgba(0, 0, 0, 0.7);
150
+ padding: 10px;
151
+ border-radius: 0 0 8px 8px;
152
+ margin-top: -5px;
153
+ }
154
+
155
+ .control-group {
156
+ display: flex;
157
+ align-items: center;
158
+ gap: 15px;
159
+ }
160
+
161
+ .control-btn {
162
+ background: none;
163
+ border: none;
164
+ color: white;
165
+ font-size: 1.2rem;
166
+ cursor: pointer;
167
+ padding: 5px;
168
+ border-radius: 50%;
169
+ width: 36px;
170
+ height: 36px;
171
+ display: flex;
172
+ align-items: center;
173
+ justify-content: center;
174
+ transition: background-color 0.2s;
175
+ }
176
+
177
+ .control-btn:hover {
178
+ background-color: rgba(255, 255, 255, 0.2);
179
+ }
180
+
181
+ .progress-container {
182
+ flex-grow: 1;
183
+ margin: 0 15px;
184
+ height: 5px;
185
+ background-color: rgba(255, 255, 255, 0.2);
186
+ border-radius: 5px;
187
+ cursor: pointer;
188
+ position: relative;
189
+ }
190
+
191
+ .progress-bar {
192
+ height: 100%;
193
+ background-color: #3498db;
194
+ border-radius: 5px;
195
+ width: 0%;
196
+ position: relative;
197
+ }
198
+
199
+ .progress-time {
200
+ position: absolute;
201
+ top: -25px;
202
+ transform: translateX(-50%);
203
+ background-color: rgba(0, 0, 0, 0.7);
204
+ color: white;
205
+ padding: 3px 6px;
206
+ border-radius: 4px;
207
+ font-size: 0.8rem;
208
+ display: none;
209
+ }
210
+
211
+ .progress-container:hover .progress-time {
212
+ display: block;
213
+ }
214
+
215
+ .close-player {
216
+ position: absolute;
217
+ top: -40px;
218
+ right: 0;
219
+ background: none;
220
+ border: none;
221
+ color: white;
222
+ font-size: 1.5rem;
223
+ cursor: pointer;
224
+ }
225
+
226
+ .time-display {
227
+ color: white;
228
+ font-size: 0.9rem;
229
+ min-width: 100px;
230
+ text-align: center;
231
+ }
232
+
233
+ .volume-container {
234
+ display: flex;
235
+ align-items: center;
236
+ gap: 5px;
237
+ }
238
+
239
+ .volume-slider {
240
+ width: 80px;
241
+ cursor: pointer;
242
+ }
243
+
244
+ .no-results {
245
+ text-align: center;
246
+ padding: 40px;
247
+ color: #666;
248
+ font-size: 1.2rem;
249
+ grid-column: 1 / -1;
250
+ }
251
+
252
+ @media (max-width: 768px) {
253
+ .video-list {
254
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
255
+ }
256
+
257
+ .control-group {
258
+ gap: 8px;
259
+ }
260
+
261
+ .time-display {
262
+ min-width: 80px;
263
+ font-size: 0.8rem;
264
+ }
265
+
266
+ .volume-slider {
267
+ width: 60px;
268
+ }
269
+ }
270
+
271
+ @media (max-width: 480px) {
272
+ .video-list {
273
+ grid-template-columns: 1fr;
274
+ }
275
+
276
+ #search {
277
+ width: 90%;
278
+ }
279
+
280
+ .video-player-wrapper {
281
+ width: 95%;
282
+ }
283
+
284
+ .control-btn {
285
+ font-size: 1rem;
286
+ width: 30px;
287
+ height: 30px;
288
  }
289
  }
290
  </style>
291
  </head>
292
+ <body>
293
+ <div class="container">
294
+ <header>
295
+ <h1>Video Player</h1>
296
+ </header>
297
+
298
+ <div class="search-container">
299
+ <input type="text" id="search" placeholder="Search videos...">
 
 
300
  </div>
301
+
302
+ <div class="video-list" id="videoList">
303
+ <!-- Videos will be loaded here -->
 
 
 
 
 
304
  </div>
305
+ </div>
306
+
307
+ <div class="video-player-container" id="playerContainer">
308
+ <div class="video-player-wrapper">
309
+ <button class="close-player" id="closePlayer">&times;</button>
310
+ <video id="videoPlayer"></video>
311
+ <div class="player-controls">
312
+ <div class="control-group">
313
+ <button class="control-btn" id="playPauseBtn">&#9658;</button>
314
+ <button class="control-btn" id="skipBackBtn">&#8630;</button>
315
+ <button class="control-btn" id="skipForwardBtn">&#8631;</button>
316
+ <div class="time-display">
317
+ <span id="currentTime">0:00</span> / <span id="duration">0:00</span>
318
+ </div>
319
+ </div>
320
+
321
+ <div class="progress-container" id="progressContainer">
322
+ <div class="progress-bar" id="progressBar"></div>
323
+ <div class="progress-time" id="progressTime">0:00</div>
324
+ </div>
325
+
326
+ <div class="control-group">
327
+ <div class="volume-container">
328
+ <button class="control-btn" id="volumeBtn">&#128266;</button>
329
+ <input type="range" class="volume-slider" id="volumeSlider" min="0" max="1" step="0.01" value="1">
330
+ </div>
331
+ <button class="control-btn" id="fullscreenBtn">&#9974;</button>
332
+ </div>
333
+ </div>
334
  </div>
 
 
 
335
  </div>
336
+
 
337
  <script>
338
+ // Global variables
339
+ let videos = [];
340
+ let lastTapTime = 0;
341
+
342
+ // DOM elements
343
+ const videoListElement = document.getElementById('videoList');
344
+ const searchInput = document.getElementById('search');
345
+ const playerContainer = document.getElementById('playerContainer');
346
+ const videoPlayer = document.getElementById('videoPlayer');
347
+ const playPauseBtn = document.getElementById('playPauseBtn');
348
+ const skipBackBtn = document.getElementById('skipBackBtn');
349
+ const skipForwardBtn = document.getElementById('skipForwardBtn');
350
+ const progressBar = document.getElementById('progressBar');
351
+ const progressContainer = document.getElementById('progressContainer');
352
+ const progressTime = document.getElementById('progressTime');
353
+ const currentTimeDisplay = document.getElementById('currentTime');
354
+ const durationDisplay = document.getElementById('duration');
355
+ const volumeBtn = document.getElementById('volumeBtn');
356
+ const volumeSlider = document.getElementById('volumeSlider');
357
+ const fullscreenBtn = document.getElementById('fullscreenBtn');
358
+ const closePlayer = document.getElementById('closePlayer');
359
+
360
+ // Load videos from JSON
361
+ async function loadVideos() {
362
+ try {
363
+ const response = await fetch('database.json');
364
+ if (!response.ok) {
365
+ throw new Error('Failed to load videos');
366
  }
367
+ videos = await response.json();
368
+ displayVideos(videos);
369
+ } catch (error) {
370
+ console.error('Error loading videos:', error);
371
+ videoListElement.innerHTML = '<div class="no-results">Failed to load videos. Please try again later.</div>';
372
+ }
373
+ }
374
+
375
+ // Display videos in the list
376
+ function displayVideos(videosToDisplay) {
377
+ if (videosToDisplay.length === 0) {
378
+ videoListElement.innerHTML = '<div class="no-results">No videos found. Try a different search.</div>';
379
+ return;
380
+ }
381
+
382
+ videoListElement.innerHTML = videosToDisplay.map(video => `
383
+ <div class="video-item" data-url="${video.url}" data-title="${video.title}">
384
+ <div class="video-thumbnail">
385
+ <img src="${video.thumbnail || 'https://via.placeholder.com/300x169?text=No+Thumbnail'}" alt="${video.title}">
386
+ </div>
387
+ <div class="video-info">
388
+ <h3 class="video-title">${video.title}</h3>
389
+ </div>
390
+ </div>
391
+ `).join('');
392
+
393
+ // Add click event to video items
394
+ document.querySelectorAll('.video-item').forEach(item => {
395
+ item.addEventListener('click', () => {
396
+ const videoUrl = item.getAttribute('data-url');
397
+ const videoTitle = item.getAttribute('data-title');
398
+ playVideo(videoUrl, videoTitle);
399
+ });
400
  });
401
+ }
402
+
403
+ // Play selected video
404
+ function playVideo(url, title) {
405
+ videoPlayer.src = url;
406
+ document.title = `${title} - Video Player`;
407
+
408
+ // Show player
409
+ playerContainer.classList.add('show');
410
+
411
+ // Attempt to play (may need user interaction on some browsers)
412
+ const playPromise = videoPlayer.play();
413
+
414
+ if (playPromise !== undefined) {
415
+ playPromise.catch(error => {
416
+ console.log('Auto-play prevented:', error);
 
417
  });
418
  }
419
+ }
420
+
421
+ // Close video player
422
+ function closeVideoPlayer() {
423
+ videoPlayer.pause();
424
+ playerContainer.classList.remove('show');
425
+ document.title = 'Video Player';
426
+ }
427
+
428
+ // Format time (seconds to MM:SS)
429
+ function formatTime(seconds) {
430
+ const minutes = Math.floor(seconds / 60);
431
+ const remainingSeconds = Math.floor(seconds % 60);
432
+ return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`;
433
+ }
434
+
435
+ // Update progress bar
436
+ function updateProgressBar() {
437
+ const currentTime = videoPlayer.currentTime;
438
+ const duration = videoPlayer.duration;
439
+
440
+ if (duration) {
441
+ const progressPercent = (currentTime / duration) * 100;
442
+ progressBar.style.width = `${progressPercent}%`;
443
+ currentTimeDisplay.textContent = formatTime(currentTime);
444
+ durationDisplay.textContent = formatTime(duration);
445
+ }
446
+ }
447
+
448
+ // Skip forward or backward
449
+ function skip(seconds) {
450
+ videoPlayer.currentTime += seconds;
451
+ }
452
+
453
+ // Toggle play/pause
454
+ function togglePlayPause() {
455
+ if (videoPlayer.paused) {
456
+ videoPlayer.play();
457
+ playPauseBtn.innerHTML = '&#10074;&#10074;';
458
+ } else {
459
+ videoPlayer.pause();
460
+ playPauseBtn.innerHTML = '&#9658;';
461
+ }
462
+ }
463
+
464
+ // Toggle mute
465
+ function toggleMute() {
466
+ videoPlayer.muted = !videoPlayer.muted;
467
+ if (videoPlayer.muted) {
468
+ volumeBtn.innerHTML = '&#128263;';
469
+ volumeSlider.value = 0;
470
+ } else {
471
+ volumeBtn.innerHTML = '&#128266;';
472
+ volumeSlider.value = videoPlayer.volume;
473
+ }
474
+ }
475
+
476
+ // Update volume
477
+ function updateVolume() {
478
+ videoPlayer.volume = volumeSlider.value;
479
+ if (videoPlayer.volume === 0) {
480
+ volumeBtn.innerHTML = '&#128263;';
481
+ } else {
482
+ volumeBtn.innerHTML = '&#128266;';
483
+ }
484
+ }
485
+
486
+ // Seek to position in video
487
+ function seek(e) {
488
+ const width = this.clientWidth;
489
+ const clickX = e.offsetX;
490
+ const duration = videoPlayer.duration;
491
+ videoPlayer.currentTime = (clickX / width) * duration;
492
+ }
493
+
494
+ // Update progress time indicator
495
+ function updateProgressTime(e) {
496
+ const width = this.clientWidth;
497
+ const clickX = e.offsetX;
498
+ const duration = videoPlayer.duration;
499
+ const seekTime = (clickX / width) * duration;
500
+ progressTime.textContent = formatTime(seekTime);
501
+
502
+ // Position the time indicator
503
+ const progressContainerRect = progressContainer.getBoundingClientRect();
504
+ const progressTimeWidth = progressTime.offsetWidth;
505
+ let leftPosition = e.clientX - progressContainerRect.left - (progressTimeWidth / 2);
506
+
507
+ // Keep within bounds
508
+ leftPosition = Math.max(0, Math.min(leftPosition, progressContainerRect.width - progressTimeWidth));
509
+ progressTime.style.left = `${leftPosition}px`;
510
+ }
511
+
512
+ // Toggle fullscreen
513
+ function toggleFullscreen() {
514
+ if (!document.fullscreenElement) {
515
+ playerContainer.requestFullscreen().catch(err => {
516
+ console.error(`Error attempting to enable fullscreen: ${err.message}`);
517
+ });
518
+ } else {
519
+ document.exitFullscreen();
520
+ }
521
+ }
522
+
523
+ // Handle double tap for skip
524
+ function handleDoubleTap(e) {
525
+ const currentTime = Date.now();
526
+ const tapLength = currentTime - lastTapTime;
527
+
528
+ if (tapLength < 300 && tapLength > 0) {
529
+ // Double tap detected
530
+ const rect = videoPlayer.getBoundingClientRect();
531
+ const tapPosition = e.clientX - rect.left;
532
+ const halfWidth = rect.width / 2;
533
+
534
+ if (tapPosition < halfWidth) {
535
+ // Left side - skip backward
536
+ skip(-10);
537
+ } else {
538
+ // Right side - skip forward
539
+ skip(10);
540
  }
541
+ }
542
+
543
+ lastTapTime = currentTime;
544
+ }
545
+
546
+ // Event listeners
547
+ searchInput.addEventListener('input', () => {
548
+ const searchTerm = searchInput.value.toLowerCase();
549
+ const filteredVideos = videos.filter(video =>
550
+ video.title.toLowerCase().includes(searchTerm)
551
+ );
552
+ displayVideos(filteredVideos);
553
+ });
554
+
555
+ videoPlayer.addEventListener('timeupdate', updateProgressBar);
556
+ videoPlayer.addEventListener('ended', () => {
557
+ playPauseBtn.innerHTML = '&#9658;';
558
+ });
559
+ videoPlayer.addEventListener('click', togglePlayPause);
560
+ videoPlayer.addEventListener('dblclick', handleDoubleTap);
561
+
562
+ playPauseBtn.addEventListener('click', togglePlayPause);
563
+ skipBackBtn.addEventListener('click', () => skip(-10));
564
+ skipForwardBtn.addEventListener('click', () => skip(10));
565
+
566
+ progressContainer.addEventListener('click', seek);
567
+ progressContainer.addEventListener('mousemove', updateProgressTime);
568
+
569
+ volumeBtn.addEventListener('click', toggleMute);
570
+ volumeSlider.addEventListener('input', updateVolume);
571
+
572
+ fullscreenBtn.addEventListener('click', toggleFullscreen);
573
+ closePlayer.addEventListener('click', closeVideoPlayer);
574
+
575
+ // Keyboard controls
576
+ document.addEventListener('keydown', (e) => {
577
+ if (!playerContainer.classList.contains('show')) return;
578
+
579
+ switch (e.key) {
580
+ case ' ':
581
+ case 'k':
582
+ togglePlayPause();
583
+ e.preventDefault();
584
+ break;
585
+ case 'ArrowLeft':
586
+ skip(-5);
587
+ break;
588
+ case 'ArrowRight':
589
+ skip(5);
590
+ break;
591
+ case 'ArrowUp':
592
+ videoPlayer.volume = Math.min(1, videoPlayer.volume + 0.1);
593
+ volumeSlider.value = videoPlayer.volume;
594
+ updateVolume();
595
+ break;
596
+ case 'ArrowDown':
597
+ videoPlayer.volume = Math.max(0, videoPlayer.volume - 0.1);
598
+ volumeSlider.value = videoPlayer.volume;
599
+ updateVolume();
600
+ break;
601
+ case 'm':
602
+ toggleMute();
603
+ break;
604
+ case 'f':
605
+ toggleFullscreen();
606
+ break;
607
+ case 'Escape':
608
+ closeVideoPlayer();
609
+ break;
610
  }
611
  });
612
+
613
+ // Initialize
614
+ loadVideos();
615
  </script>
616
  </body>
617
+ </html>