zoomora 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/zoomora.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /*!
2
- * Zoomora Lightbox Plugin v1.1.0
2
+ * Zoomora Lightbox Plugin v1.2.0
3
3
  * A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features
4
4
  *
5
- * Copyright (c) 2025 Faruk Ahmed (FrontTheme)
5
+ * Copyright (c) 2026 Faruk Ahmed (FrontTheme)
6
6
  * Licensed under MIT License
7
7
  */
8
8
 
@@ -46,6 +46,7 @@ import './styles/zoomora.scss';
46
46
  maxZoomScale: 3, // Maximum zoom scale
47
47
  zoomStep: 0.1, // Zoom step for scroll wheel
48
48
  animationDuration: 300, // Animation duration in ms
49
+ closeOnBackgroundClick: true, // Close lightbox when clicking on background
49
50
  onOpen: null, // Callback when lightbox opens
50
51
  onClose: null, // Callback when lightbox closes
51
52
  onNext: null, // Callback when navigating to next item
@@ -247,7 +248,7 @@ import './styles/zoomora.scss';
247
248
  // Lightbox click to close
248
249
  this.addEventListener(this.zoomora, 'click', this.boundMethods.handleZoomoraClick);
249
250
 
250
- // Content click for zoom toggle
251
+ // Content click for zoom toggle and background click
251
252
  this.addEventListener(this.content, 'click', this.boundMethods.handleContentClick);
252
253
 
253
254
  // Mouse drag events
@@ -344,16 +345,25 @@ import './styles/zoomora.scss';
344
345
  * Handle fullscreen change events
345
346
  */
346
347
  handleFullscreenChange() {
347
- const isInFullscreen = document.fullscreenElement ||
348
+ const isInFullscreen = !!(
349
+ document.fullscreenElement ||
348
350
  document.webkitFullscreenElement ||
349
351
  document.mozFullScreenElement ||
350
- document.msFullscreenElement;
352
+ document.msFullscreenElement
353
+ );
351
354
 
355
+ // Only update if state changed from fullscreen to not fullscreen
352
356
  if (!isInFullscreen && this.isFullscreen) {
353
357
  this.isFullscreen = false;
354
358
  this.zoomora.classList.remove('fullscreen');
355
359
  this.updateButtons();
356
360
  }
361
+ // Update if entering fullscreen
362
+ else if (isInFullscreen && !this.isFullscreen) {
363
+ this.isFullscreen = true;
364
+ this.zoomora.classList.add('fullscreen');
365
+ this.updateButtons();
366
+ }
357
367
  }
358
368
 
359
369
  /**
@@ -361,7 +371,7 @@ import './styles/zoomora.scss';
361
371
  * @param {Event} e - Click event
362
372
  */
363
373
  handleZoomoraClick(e) {
364
- if (e.target === this.zoomora) {
374
+ if (e.target === this.zoomora && this.options.closeOnBackgroundClick) {
365
375
  this.close();
366
376
  }
367
377
  }
@@ -376,9 +386,60 @@ import './styles/zoomora.scss';
376
386
  return;
377
387
  }
378
388
 
379
- const media = e.target.closest('.zoomora-media');
380
- if (media && !media.classList.contains('no-zoom')) {
381
- this.toggleZoom();
389
+ // Don't close on header clicks
390
+ if (this.header && this.header.contains(e.target)) {
391
+ return;
392
+ }
393
+
394
+ // Don't close on button clicks
395
+ if (e.target.closest('button')) {
396
+ return;
397
+ }
398
+
399
+ // Check if click is directly on actual media element (img, video, iframe)
400
+ const mediaElement = e.target.closest('.zoomora-media, .zoomora-video, .zoomora-iframe');
401
+
402
+ if (mediaElement) {
403
+ // Only toggle zoom for images
404
+ if (mediaElement.classList.contains('zoomora-media') && !mediaElement.classList.contains('no-zoom')) {
405
+ this.toggleZoom();
406
+ }
407
+ return;
408
+ }
409
+
410
+ // Check if clicking inside video container but not on video itself
411
+ const videoContainer = e.target.closest('.zoomora-video-container');
412
+ if (videoContainer) {
413
+ // If clicking on the play button, don't close
414
+ if (e.target.closest('.zoomora-play-button')) {
415
+ return;
416
+ }
417
+ // If clicking on background area of video container, close
418
+ if (this.options.closeOnBackgroundClick) {
419
+ this.close();
420
+ }
421
+ return;
422
+ }
423
+
424
+ // Check if clicking on background elements (including when zoomed)
425
+ // This checks the actual target element, not just closest()
426
+ const clickedElement = e.target;
427
+ const isBackgroundElement =
428
+ clickedElement.classList.contains('zoomora-content') ||
429
+ clickedElement.classList.contains('zoomora-slide-container') ||
430
+ clickedElement.classList.contains('zoomora-slide') ||
431
+ clickedElement.classList.contains('zoomora-slides-container') ||
432
+ clickedElement.id === 'zoomoraContent' ||
433
+ clickedElement.id === 'zoomoraSlidesContainer';
434
+
435
+ if (isBackgroundElement && this.options.closeOnBackgroundClick) {
436
+ this.close();
437
+ return;
438
+ }
439
+
440
+ // If we reach here and no media was clicked, close
441
+ if (this.options.closeOnBackgroundClick) {
442
+ this.close();
382
443
  }
383
444
  }
384
445
 
@@ -970,11 +1031,6 @@ import './styles/zoomora.scss';
970
1031
  }
971
1032
  }
972
1033
 
973
- /**
974
- * Calculate zoom levels for an image
975
- * @param {HTMLImageElement} img - Image element
976
- * @returns {Object} Zoom configuration
977
- */
978
1034
  /**
979
1035
  * Calculate zoom levels for an image
980
1036
  * @param {HTMLImageElement} img - Image element
@@ -1151,7 +1207,6 @@ import './styles/zoomora.scss';
1151
1207
  const zoomConfig = this.calculateZoomLevels(media);
1152
1208
 
1153
1209
  if (!zoomConfig.canZoom) {
1154
- console.log('Image cannot be zoomed (already at full size or larger)');
1155
1210
  return;
1156
1211
  }
1157
1212
 
@@ -1193,8 +1248,6 @@ import './styles/zoomora.scss';
1193
1248
  media.style.transform = `translate(0px, 0px) scale(${targetScale})`;
1194
1249
  media.style.cursor = 'grab';
1195
1250
  media.classList.add('zoomed');
1196
-
1197
- console.log(`Zoomed to level ${currentLevel}/${zoomConfig.levels.length - 1} (${(targetScale * 100).toFixed(0)}%)`);
1198
1251
  }
1199
1252
  }
1200
1253
 
@@ -1231,21 +1284,50 @@ import './styles/zoomora.scss';
1231
1284
  */
1232
1285
  enterFullscreen() {
1233
1286
  const element = this.zoomora;
1234
- const requestFullscreen = element.requestFullscreen ||
1235
- element.webkitRequestFullscreen ||
1236
- element.mozRequestFullScreen ||
1237
- element.msRequestFullscreen;
1238
1287
 
1239
- if (requestFullscreen) {
1240
- requestFullscreen.call(element).then(() => {
1288
+ try {
1289
+ // Try standard API first
1290
+ if (element.requestFullscreen) {
1291
+ element.requestFullscreen()
1292
+ .then(() => {
1293
+ this.isFullscreen = true;
1294
+ this.zoomora.classList.add('fullscreen');
1295
+ this.updateButtons();
1296
+ })
1297
+ .catch(err => {
1298
+ console.warn('Zoomora: Fullscreen request failed:', err.message);
1299
+ this.fallbackFullscreen();
1300
+ });
1301
+ }
1302
+ // Try webkit (Safari, older Chrome)
1303
+ else if (element.webkitRequestFullscreen) {
1304
+ element.webkitRequestFullscreen();
1305
+ // Webkit doesn't return a promise, so set state immediately
1306
+ this.isFullscreen = true;
1307
+ this.zoomora.classList.add('fullscreen');
1308
+ this.updateButtons();
1309
+ }
1310
+ // Try moz (Firefox)
1311
+ else if (element.mozRequestFullScreen) {
1312
+ element.mozRequestFullScreen();
1313
+ this.isFullscreen = true;
1314
+ this.zoomora.classList.add('fullscreen');
1315
+ this.updateButtons();
1316
+ }
1317
+ // Try ms (IE11)
1318
+ else if (element.msRequestFullscreen) {
1319
+ element.msRequestFullscreen();
1241
1320
  this.isFullscreen = true;
1242
1321
  this.zoomora.classList.add('fullscreen');
1243
1322
  this.updateButtons();
1244
- }).catch(err => {
1245
- console.warn('Zoomora: Could not enter fullscreen:', err);
1323
+ }
1324
+ // Fallback to CSS fullscreen
1325
+ else {
1326
+ console.warn('Zoomora: Fullscreen API not supported, using CSS fallback');
1246
1327
  this.fallbackFullscreen();
1247
- });
1248
- } else {
1328
+ }
1329
+ } catch (error) {
1330
+ console.error('Zoomora: Error entering fullscreen:', error);
1249
1331
  this.fallbackFullscreen();
1250
1332
  }
1251
1333
  }
@@ -1254,30 +1336,61 @@ import './styles/zoomora.scss';
1254
1336
  * Exit fullscreen mode
1255
1337
  */
1256
1338
  exitFullscreen() {
1257
- const isInFullscreen = document.fullscreenElement ||
1339
+ // First check if we're actually in fullscreen
1340
+ const isInFullscreen = !!(
1341
+ document.fullscreenElement ||
1258
1342
  document.webkitFullscreenElement ||
1259
1343
  document.mozFullScreenElement ||
1260
- document.msFullscreenElement;
1261
-
1262
- if (isInFullscreen) {
1263
- const exitFullscreen = document.exitFullscreen ||
1264
- document.webkitExitFullscreen ||
1265
- document.mozCancelFullScreen ||
1266
- document.msExitFullscreen;
1267
-
1268
- if (exitFullscreen) {
1269
- exitFullscreen.call(document).then(() => {
1270
- this.isFullscreen = false;
1271
- this.zoomora.classList.remove('fullscreen');
1272
- this.updateButtons();
1273
- }).catch(err => {
1274
- console.warn('Zoomora: Could not exit fullscreen:', err);
1275
- this.fallbackExitFullscreen();
1276
- });
1277
- } else {
1344
+ document.msFullscreenElement
1345
+ );
1346
+
1347
+ if (!isInFullscreen) {
1348
+ // Not in real fullscreen, just exit CSS fullscreen
1349
+ this.fallbackExitFullscreen();
1350
+ return;
1351
+ }
1352
+
1353
+ try {
1354
+ // Try standard API first
1355
+ if (document.exitFullscreen) {
1356
+ document.exitFullscreen()
1357
+ .then(() => {
1358
+ this.isFullscreen = false;
1359
+ this.zoomora.classList.remove('fullscreen');
1360
+ this.updateButtons();
1361
+ })
1362
+ .catch(err => {
1363
+ console.warn('Zoomora: Exit fullscreen failed:', err.message);
1364
+ this.fallbackExitFullscreen();
1365
+ });
1366
+ }
1367
+ // Try webkit
1368
+ else if (document.webkitExitFullscreen) {
1369
+ document.webkitExitFullscreen();
1370
+ this.isFullscreen = false;
1371
+ this.zoomora.classList.remove('fullscreen');
1372
+ this.updateButtons();
1373
+ }
1374
+ // Try moz
1375
+ else if (document.mozCancelFullScreen) {
1376
+ document.mozCancelFullScreen();
1377
+ this.isFullscreen = false;
1378
+ this.zoomora.classList.remove('fullscreen');
1379
+ this.updateButtons();
1380
+ }
1381
+ // Try ms
1382
+ else if (document.msExitFullscreen) {
1383
+ document.msExitFullscreen();
1384
+ this.isFullscreen = false;
1385
+ this.zoomora.classList.remove('fullscreen');
1386
+ this.updateButtons();
1387
+ }
1388
+ // Fallback
1389
+ else {
1278
1390
  this.fallbackExitFullscreen();
1279
1391
  }
1280
- } else {
1392
+ } catch (error) {
1393
+ console.error('Zoomora: Error exiting fullscreen:', error);
1281
1394
  this.fallbackExitFullscreen();
1282
1395
  }
1283
1396
  }