Docfile commited on
Commit
dff3fca
·
verified ·
1 Parent(s): efcc0c3

Update templates/viewer.html

Browse files
Files changed (1) hide show
  1. templates/viewer.html +96 -152
templates/viewer.html CHANGED
@@ -1,79 +1,54 @@
1
  <!DOCTYPE html>
2
- <html lang="fr">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Visualiseur de PDF</title>
7
  <style>
8
- :root {
9
- --primary-color: #007bff;
10
- --primary-hover: #0056b3;
11
- --bg-color: #f8f9fa;
12
- --border-color: #ddd;
13
- --text-color: #333;
14
- --error-color: #dc3545;
15
- }
16
-
17
- * {
18
- box-sizing: border-box;
19
  margin: 0;
20
  padding: 0;
21
- }
22
-
23
- body {
24
- font-family: system-ui, -apple-system, sans-serif;
25
- color: var(--text-color);
26
- line-height: 1.6;
27
- min-height: 100vh;
28
  display: flex;
29
  flex-direction: column;
 
30
  }
31
 
32
  #pdf-container {
33
- flex: 1;
34
  overflow-y: auto;
35
- padding: 20px;
36
- background-color: var(--bg-color);
37
- scroll-behavior: smooth;
38
  }
39
 
40
  .page {
41
- max-width: 1000px;
42
- margin: 0 auto 30px;
 
43
  background-color: #fff;
44
- border-radius: 8px;
45
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
46
- padding: 20px;
47
- position: relative;
48
- transition: transform 0.2s ease;
49
- }
50
-
51
- .page:hover {
52
- transform: translateY(-2px);
53
  }
54
 
55
  .page img {
56
- width: 100%;
57
  height: auto;
58
- border-radius: 4px;
59
- display: block;
60
  }
61
 
62
  .page button {
63
- margin-top: 15px;
64
- padding: 12px 20px;
65
- background-color: var(--primary-color);
66
  color: white;
67
  border: none;
68
- border-radius: 6px;
69
  cursor: pointer;
70
- transition: background-color 0.2s ease;
71
- font-weight: 500;
72
- width: 100%;
73
  }
74
 
75
  .page button:hover {
76
- background-color: var(--primary-hover);
77
  }
78
 
79
  .loading-indicator {
@@ -81,119 +56,87 @@
81
  top: 50%;
82
  left: 50%;
83
  transform: translate(-50%, -50%);
84
- width: 40px;
85
- height: 40px;
86
- border: 3px solid rgba(0, 123, 255, 0.2);
87
- border-top-color: var(--primary-color);
88
  border-radius: 50%;
 
 
89
  animation: spin 1s linear infinite;
90
- display: none;
91
  }
92
 
93
  .page.loading .loading-indicator {
94
- display: block;
95
  }
96
 
97
- .error-message {
98
- color: var(--error-color);
99
- text-align: center;
100
- margin-top: 15px;
101
- font-weight: 500;
102
  }
103
 
104
  #navigation {
105
- background-color: #fff;
106
- padding: 15px;
107
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
108
- position: sticky;
 
109
  top: 0;
110
- z-index: 100;
111
- display: flex;
112
- align-items: center;
113
- justify-content: center;
114
- gap: 10px;
115
- flex-wrap: wrap;
116
  }
117
 
118
  #navigation button {
119
- padding: 8px 16px;
120
- background-color: var(--primary-color);
 
121
  color: white;
122
  border: none;
123
- border-radius: 6px;
124
  cursor: pointer;
125
- transition: all 0.2s ease;
126
- font-weight: 500;
127
- }
128
-
129
- #navigation button:hover:not(:disabled) {
130
- background-color: var(--primary-hover);
131
- transform: translateY(-1px);
132
  }
133
 
134
  #navigation button:disabled {
135
- opacity: 0.5;
136
- cursor: not-allowed;
137
- }
138
-
139
- #pageNumberInput {
140
- width: 70px;
141
- padding: 8px;
142
- border: 1px solid var(--border-color);
143
- border-radius: 4px;
144
- text-align: center;
145
  }
146
 
147
  @keyframes spin {
148
- to { transform: translate(-50%, -50%) rotate(360deg); }
149
- }
150
-
151
- @media (max-width: 600px) {
152
- #navigation {
153
- padding: 10px;
154
- font-size: 14px;
155
- }
156
-
157
- #navigation button {
158
- padding: 6px 12px;
159
- }
160
-
161
- .page {
162
- margin: 0 10px 20px;
163
- padding: 15px;
164
- }
165
  }
166
  </style>
167
  </head>
168
  <body>
169
  <div id="navigation">
170
- <button id="prevPage">Précédente</button>
171
  <span>Page <span id="currentPage">1</span> / <span id="totalPagesSpan">210</span></span>
172
- <button id="nextPage">Suivante</button>
173
- <button id="gotoPage">Aller à</button>
174
- <input type="number" id="pageNumberInput" min="1" value="1" aria-label="Numéro de page">
175
  </div>
176
 
177
- <div id="pdf-container"></div>
 
 
178
 
179
  <script>
 
180
  const totalPages = 210;
181
- const lowResEndpoint = "/low_res/";
182
- const highResEndpoint = "/high_res/";
183
  let currentPage = 1;
184
 
185
- const elements = {
186
- pdfContainer: document.getElementById("pdf-container"),
187
- prevPageButton: document.getElementById("prevPage"),
188
- nextPageButton: document.getElementById("nextPage"),
189
- currentPageSpan: document.getElementById("currentPage"),
190
- totalPagesSpan: document.getElementById("totalPagesSpan"),
191
- gotoPageButton: document.getElementById("gotoPage"),
192
- pageNumberInput: document.getElementById("pageNumberInput")
193
- };
194
 
195
- elements.totalPagesSpan.textContent = totalPages;
196
 
 
197
  function showLoadingIndicator(pageDiv) {
198
  const loadingIndicator = document.createElement('div');
199
  loadingIndicator.className = 'loading-indicator';
@@ -201,28 +144,28 @@
201
  pageDiv.classList.add('loading');
202
  }
203
 
 
204
  function hideLoadingIndicator(pageDiv) {
205
  const loadingIndicator = pageDiv.querySelector('.loading-indicator');
206
  if (loadingIndicator) {
207
- loadingIndicator.remove();
208
  }
209
  pageDiv.classList.remove('loading');
210
  }
211
 
 
212
  function loadPage(pageNumber) {
213
  const pageDiv = document.getElementById(`page-${pageNumber}`);
214
- if (!pageDiv) return;
215
 
216
  showLoadingIndicator(pageDiv);
217
 
218
  const img = new Image();
219
  img.src = `${lowResEndpoint}${pageNumber}`;
220
  img.alt = `Page ${pageNumber}`;
221
- img.loading = "lazy";
222
-
223
  img.onload = () => {
224
  hideLoadingIndicator(pageDiv);
225
- pageDiv.innerHTML = '';
226
  pageDiv.appendChild(img);
227
 
228
  const button = document.createElement("button");
@@ -230,7 +173,6 @@
230
  button.onclick = () => downloadHighRes(pageNumber);
231
  pageDiv.appendChild(button);
232
  };
233
-
234
  img.onerror = () => {
235
  hideLoadingIndicator(pageDiv);
236
  const errorMsg = document.createElement('p');
@@ -240,10 +182,13 @@
240
  };
241
  }
242
 
 
243
  function downloadHighRes(pageNumber) {
244
- window.open(`${highResEndpoint}${pageNumber}`, "_blank");
 
245
  }
246
 
 
247
  function initLazyLoading() {
248
  const observer = new IntersectionObserver(entries => {
249
  entries.forEach(entry => {
@@ -253,51 +198,50 @@
253
  observer.unobserve(entry.target);
254
  }
255
  });
256
- }, {
257
- rootMargin: '50px'
258
  });
259
 
260
  for (let pageNumber = 1; pageNumber <= totalPages; pageNumber++) {
261
  const pageDiv = document.createElement('div');
262
  pageDiv.className = 'page';
263
  pageDiv.id = `page-${pageNumber}`;
264
- elements.pdfContainer.appendChild(pageDiv);
265
  observer.observe(pageDiv);
266
  }
267
  }
268
 
 
269
  function updateNavigation() {
270
- elements.currentPageSpan.textContent = currentPage;
271
- elements.prevPageButton.disabled = currentPage === 1;
272
- elements.nextPageButton.disabled = currentPage === totalPages;
273
- elements.pageNumberInput.value = currentPage;
274
  }
275
 
276
  function goToPage(pageNumber) {
277
- if (pageNumber >= 1 && pageNumber <= totalPages) {
278
- currentPage = pageNumber;
279
- updateNavigation();
280
- document.getElementById(`page-${pageNumber}`)?.scrollIntoView({
281
- behavior: 'smooth',
282
- block: 'start'
283
- });
284
- }
285
  }
286
 
287
- elements.prevPageButton.addEventListener('click', () => goToPage(currentPage - 1));
288
- elements.nextPageButton.addEventListener('click', () => goToPage(currentPage + 1));
289
- elements.gotoPageButton.addEventListener('click', () => {
290
- const pageNumber = parseInt(elements.pageNumberInput.value);
291
- if (pageNumber) goToPage(pageNumber);
292
  });
293
 
294
- elements.pageNumberInput.addEventListener('keypress', (e) => {
295
- if (e.key === 'Enter') {
296
- const pageNumber = parseInt(e.target.value);
297
- if (pageNumber) goToPage(pageNumber);
298
- }
 
 
299
  });
300
 
 
301
  window.onload = () => {
302
  initLazyLoading();
303
  updateNavigation();
 
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>Visualiseur de PDF</title>
7
  <style>
8
+ body {
9
+ font-family: Arial, sans-serif;
 
 
 
 
 
 
 
 
 
10
  margin: 0;
11
  padding: 0;
 
 
 
 
 
 
 
12
  display: flex;
13
  flex-direction: column;
14
+ min-height: 100vh;
15
  }
16
 
17
  #pdf-container {
18
+ flex-grow: 1;
19
  overflow-y: auto;
20
+ padding: 10px;
21
+ background-color: #f8f9fa;
 
22
  }
23
 
24
  .page {
25
+ margin-bottom: 20px;
26
+ text-align: center;
27
+ border: 1px solid #ddd;
28
  background-color: #fff;
29
+ padding: 10px;
30
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
31
+ position: relative; /* Pour positionner l'indicateur de chargement */
 
 
 
 
 
 
32
  }
33
 
34
  .page img {
35
+ max-width: 100%;
36
  height: auto;
37
+ display: block; /* Empêche l'espace sous l'image */
 
38
  }
39
 
40
  .page button {
41
+ margin-top: 10px;
42
+ padding: 10px 15px;
43
+ background-color: #007bff;
44
  color: white;
45
  border: none;
46
+ border-radius: 4px;
47
  cursor: pointer;
 
 
 
48
  }
49
 
50
  .page button:hover {
51
+ background-color: #0056b3;
52
  }
53
 
54
  .loading-indicator {
 
56
  top: 50%;
57
  left: 50%;
58
  transform: translate(-50%, -50%);
59
+ border: 4px solid rgba(0, 0, 0, 0.1);
60
+ border-top: 4px solid #007bff;
 
 
61
  border-radius: 50%;
62
+ width: 30px;
63
+ height: 30px;
64
  animation: spin 1s linear infinite;
65
+ display: none; /* Masqué par défaut */
66
  }
67
 
68
  .page.loading .loading-indicator {
69
+ display: block; /* Affiché pendant le chargement */
70
  }
71
 
72
+ .page .error-message {
73
+ color: red;
74
+ margin-top: 10px;
 
 
75
  }
76
 
77
  #navigation {
78
+ background-color: #eee;
79
+ padding: 10px;
80
+ text-align: center;
81
+ border-bottom: 1px solid #ccc;
82
+ position: sticky; /* Barre de navigation fixe en haut */
83
  top: 0;
84
+ z-index: 10; /* S'assurer qu'elle est au-dessus du contenu */
 
 
 
 
 
85
  }
86
 
87
  #navigation button {
88
+ padding: 8px 12px;
89
+ margin: 0 5px;
90
+ background-color: #007bff;
91
  color: white;
92
  border: none;
93
+ border-radius: 4px;
94
  cursor: pointer;
 
 
 
 
 
 
 
95
  }
96
 
97
  #navigation button:disabled {
98
+ opacity: 0.6;
99
+ cursor: default;
 
 
 
 
 
 
 
 
100
  }
101
 
102
  @keyframes spin {
103
+ 0% { transform: translate(-50%, -50%) rotate(0deg); }
104
+ 100% { transform: translate(-50%, -50%) rotate(360deg); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
106
  </style>
107
  </head>
108
  <body>
109
  <div id="navigation">
110
+ <button id="prevPage">Page Précédente</button>
111
  <span>Page <span id="currentPage">1</span> / <span id="totalPagesSpan">210</span></span>
112
+ <button id="nextPage">Page Suivante</button>
113
+ <button id="gotoPage">Aller à la page:</button>
114
+ <input type="number" id="pageNumberInput" min="1" value="1">
115
  </div>
116
 
117
+ <div id="pdf-container">
118
+ <!-- Les pages PDF seront ajoutées ici dynamiquement -->
119
+ </div>
120
 
121
  <script>
122
+ // Configuration de l'application
123
  const totalPages = 210;
124
+ const lowResEndpoint = "/low_res/"; // Endpoint Flask pour les images basse résolution
125
+ const highResEndpoint = "/high_res/"; // Endpoint Flask pour les images haute résolution
126
  let currentPage = 1;
127
 
128
+ // Références aux éléments
129
+ const pdfContainer = document.getElementById("pdf-container");
130
+ const prevPageButton = document.getElementById("prevPage");
131
+ const nextPageButton = document.getElementById("nextPage");
132
+ const currentPageSpan = document.getElementById("currentPage");
133
+ const totalPagesSpan = document.getElementById("totalPagesSpan");
134
+ const gotoPageButton = document.getElementById("gotoPage");
135
+ const pageNumberInput = document.getElementById("pageNumberInput");
 
136
 
137
+ totalPagesSpan.textContent = totalPages;
138
 
139
+ // Fonction pour afficher un indicateur de chargement
140
  function showLoadingIndicator(pageDiv) {
141
  const loadingIndicator = document.createElement('div');
142
  loadingIndicator.className = 'loading-indicator';
 
144
  pageDiv.classList.add('loading');
145
  }
146
 
147
+ // Fonction pour masquer l'indicateur de chargement
148
  function hideLoadingIndicator(pageDiv) {
149
  const loadingIndicator = pageDiv.querySelector('.loading-indicator');
150
  if (loadingIndicator) {
151
+ pageDiv.removeChild(loadingIndicator);
152
  }
153
  pageDiv.classList.remove('loading');
154
  }
155
 
156
+ // Fonction pour charger une page spécifique
157
  function loadPage(pageNumber) {
158
  const pageDiv = document.getElementById(`page-${pageNumber}`);
159
+ if (!pageDiv) return; // Vérifier si l'élément existe
160
 
161
  showLoadingIndicator(pageDiv);
162
 
163
  const img = new Image();
164
  img.src = `${lowResEndpoint}${pageNumber}`;
165
  img.alt = `Page ${pageNumber}`;
 
 
166
  img.onload = () => {
167
  hideLoadingIndicator(pageDiv);
168
+ pageDiv.innerHTML = ''; // Nettoyer le contenu précédent
169
  pageDiv.appendChild(img);
170
 
171
  const button = document.createElement("button");
 
173
  button.onclick = () => downloadHighRes(pageNumber);
174
  pageDiv.appendChild(button);
175
  };
 
176
  img.onerror = () => {
177
  hideLoadingIndicator(pageDiv);
178
  const errorMsg = document.createElement('p');
 
182
  };
183
  }
184
 
185
+ // Fonction pour télécharger une image en haute résolution
186
  function downloadHighRes(pageNumber) {
187
+ const highResUrl = `${highResEndpoint}${pageNumber}`;
188
+ window.open(highResUrl, "_blank");
189
  }
190
 
191
+ // Initialisation de l'Intersection Observer pour le lazy loading
192
  function initLazyLoading() {
193
  const observer = new IntersectionObserver(entries => {
194
  entries.forEach(entry => {
 
198
  observer.unobserve(entry.target);
199
  }
200
  });
 
 
201
  });
202
 
203
  for (let pageNumber = 1; pageNumber <= totalPages; pageNumber++) {
204
  const pageDiv = document.createElement('div');
205
  pageDiv.className = 'page';
206
  pageDiv.id = `page-${pageNumber}`;
207
+ pdfContainer.appendChild(pageDiv);
208
  observer.observe(pageDiv);
209
  }
210
  }
211
 
212
+ // Gestion de la navigation
213
  function updateNavigation() {
214
+ currentPageSpan.textContent = currentPage;
215
+ prevPageButton.disabled = currentPage === 1;
216
+ nextPageButton.disabled = currentPage === totalPages;
 
217
  }
218
 
219
  function goToPage(pageNumber) {
220
+ if (pageNumber >= 1 && pageNumber <= totalPages) {
221
+ currentPage = pageNumber;
222
+ updateNavigation();
223
+ const pageDiv = document.getElementById(`page-${pageNumber}`);
224
+ if (pageDiv) {
225
+ pageDiv.scrollIntoView({ behavior: 'smooth' });
226
+ }
227
+ }
228
  }
229
 
230
+ prevPageButton.addEventListener('click', () => {
231
+ goToPage(currentPage - 1);
232
+
 
 
233
  });
234
 
235
+ nextPageButton.addEventListener('click', () => {
236
+ goToPage(currentPage + 1);
237
+ });
238
+
239
+ gotoPageButton.addEventListener('click', () => {
240
+ const pageNumber = parseInt(pageNumberInput.value);
241
+ goToPage(pageNumber);
242
  });
243
 
244
+ // Initialiser le visualiseur
245
  window.onload = () => {
246
  initLazyLoading();
247
  updateNavigation();