Browse Source

Some API changes and small tweaks

pull/33/head
Jānis Skarnelis 4 years ago
parent
commit
fe149b54d2
  1. 12
      README.md
  2. 2
      dist/fancybox.esm.js
  3. 2
      dist/fancybox.umd.js
  4. 2
      dist/panzoom.controls.css
  5. 2
      src/Carousel/Carousel.js
  6. 143
      src/Fancybox/Fancybox.js
  7. 13
      src/Fancybox/l10n/de.js
  8. 6
      src/Fancybox/plugins/Html/Html.js
  9. 12
      src/Fancybox/plugins/Image/Image.js
  10. 5
      src/Fancybox/plugins/Thumbs/Thumbs.js
  11. 7
      src/Panzoom/plugins/Controls/Controls.scss

12
README.md

@ -60,7 +60,7 @@ There are two ways to use Fancybox.
#### Declarative #### Declarative
Add a `data-fancybox` attribute to any element to enable Fancybox. Galleries are created by adding the same attribute `data-fancybox` value to multiple elements. Use `data-src` or `href` attribute to specify the source of the content. Add a `data-fancybox` attribute to any element to enable Fancybox. Galleries are created by adding the same attribute `data-fancybox` value to multiple elements. Use `data-src` or `href` attribute to specify the source of the content. Add a `data-caption` attribute if you want to show a caption under the content.
```jsx ```jsx
<a href="https://lipsum.app/id/1/1024x768" data-fancybox="gallery" data-caption="Optional caption"> <a href="https://lipsum.app/id/1/1024x768" data-fancybox="gallery" data-caption="Optional caption">
@ -100,6 +100,14 @@ Add a `data-fancybox` attribute to any element to enable Fancybox. Galleries are
</div> </div>
``` ```
Customize options:
```js
Fancybox.bind("[data-fancybox]", {
// Your options go here
});
```
#### Programmatic #### Programmatic
```js ```js
@ -213,4 +221,4 @@ Optionally, use CSS to customize container
## License ## License
This is commercial software. See LICENSE.md for more info. This is commercial software. See [LICENSE.md](LICENSE.md) for more info.

2
dist/fancybox.esm.js

File diff suppressed because one or more lines are too long

2
dist/fancybox.umd.js

File diff suppressed because one or more lines are too long

2
dist/panzoom.controls.css

@ -1 +1 @@
.panzoom__controls{position:absolute;bottom:16px;right:16px;display:flex;flex-direction:column;transform-origin:bottom right;transform:scale(0.75)}.panzoom__button{cursor:pointer;margin:0;padding:10px;border:0;color:#222;background:#eee}@media(hover: hover){.panzoom__button:hover{background:#ccc}}.panzoom__button svg{vertical-align:top;pointer-events:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round} .panzoom__controls{position:absolute;top:16px;left:16px;display:flex;flex-direction:column;transform-origin:top left;transform:scale(0.75)}.panzoom__button{cursor:pointer;margin:0;padding:10px;border:0;border-radius:0;color:#222;background:#eee}@media(hover: hover){.panzoom__button:hover{background:#ccc}}.panzoom__button svg{vertical-align:top;pointer-events:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

2
src/Carousel/Carousel.js

@ -34,7 +34,7 @@ const defaults = {
// Should the gap be filled before first and after last slide if `infinite: false` // Should the gap be filled before first and after last slide if `infinite: false`
fill: true, fill: true,
// Should carousel settle at specific page after drag event // Should Carousel settle at any position after a swipe.
dragFree: false, dragFree: false,
classNames: { classNames: {

143
src/Fancybox/Fancybox.js

@ -9,12 +9,6 @@ import { Carousel } from "../Carousel/Carousel.js";
import { Plugins } from "./plugins/index.js"; import { Plugins } from "./plugins/index.js";
const defaults = { const defaults = {
// If browser scrollbar should be hidden
hideScrollbar: true,
// Virtual slides
items: [],
// Index of active slide on the start // Index of active slide on the start
startIndex: 0, startIndex: 0,
@ -33,6 +27,33 @@ const defaults = {
// Should backdrop and UI elements fade in/out on start/close // Should backdrop and UI elements fade in/out on start/close
animated: true, animated: true,
// If browser scrollbar should be hidden
hideScrollbar: true,
// Element containing main structure
parentEl: null,
// Custom class name or multiple space-separated class names for the container
mainClass: null,
// Set focus on first focusable element after displaying content
autoFocus: true,
// Trap focus inside Fancybox
trapFocus: true,
// Set focus back to trigger element after closing Fancybox
placeFocusBack: true,
// Action to take when the user clicks on the backdrop
click: "close", // "close" | "next"
// Position of the close button - over the content or at top right corner of viewport
closeButton: "inside", // "inside" | "outside"
// Allow user to drag content up/down to close instance
dragToClose: true,
// Enable keyboard navigation // Enable keyboard navigation
keyboard: { keyboard: {
Escape: "close", Escape: "close",
@ -46,57 +67,32 @@ const defaults = {
ArrowLeft: "prev", ArrowLeft: "prev",
}, },
// HTML template for various elements // HTML templates for various elements
template: { template: {
// Close button icon
closeButton: closeButton:
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" tabindex="-1"><path d="M20 20L4 4m16 0L4 20"/></svg>', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" tabindex="-1"><path d="M20 20L4 4m16 0L4 20"/></svg>',
// Loading indicator icon
spinner: spinner:
'<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="25 25 50 50" tabindex="-1"><circle cx="50" cy="50" r="20"/></svg>', '<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="25 25 50 50" tabindex="-1"><circle cx="50" cy="50" r="20"/></svg>',
/* If `main` option is not provided, the structure is generated like this: // Main container element
main: null,
},
/* Note: If the `template.main` option is not provided, the structure is generated as follows by default:
<div class="fancybox__container" role="dialog" aria-modal="true" aria-hidden="true" aria-label="{{MODAL}}" tabindex="-1"> <div class="fancybox__container" role="dialog" aria-modal="true" aria-hidden="true" aria-label="{{MODAL}}" tabindex="-1">
<div class="fancybox__backdrop"></div> <div class="fancybox__backdrop"></div>
<div class="fancybox__carousel"></div> <div class="fancybox__carousel"></div>
</div> </div>
*/ */
main: null,
},
// Element containing main structure
parentEl: null,
// Custom class or space-separated classes for the main element
mainClass: null,
// Set focus on first focusable element after displaying content
autoFocus: true,
// Trap focus inside fancybox
trapFocus: true,
// Set focus back to trigger element after closing fancybox
placeFocusBack: true,
// Action to take when the user clicks on the backdrop // Localization of strings
click: "close", // close / next
// Position of the close button - over the content or at top right corner of viewport
closeButton: "inside", // "inside" | "outside"
// Allow user to drag content up/down to close instance
dragToClose: true,
// Example how to import other translations:
// `import de from "./l10n/de";`
// and then set `l10n: de` as an option
l10n: { l10n: {
CLOSE: "Close", CLOSE: "Close",
NEXT: "Next", NEXT: "Next",
PREV: "Previous", PREV: "Previous",
MODAL: "You can close this modal content with the ESC key", MODAL: "You can close this modal content with the ESC key",
ERROR: "Something Went Wrong, Please Try Again Later", ERROR: "Something Went Wrong, Please Try Again Later",
IMAGE_ERROR: "Image Not Found", IMAGE_ERROR: "Image Not Found",
ELEMENT_NOT_FOUND: "HTML Element Not Found", ELEMENT_NOT_FOUND: "HTML Element Not Found",
@ -115,11 +111,11 @@ class Fancybox extends Base {
* @constructs Fancybox * @constructs Fancybox
* @param {Object} [options] - Options for Fancybox * @param {Object} [options] - Options for Fancybox
*/ */
constructor(options = {}) { constructor(items, options = {}) {
const handleOptions = function (options) { const handleOptions = function (items, options) {
const firstOpts = extend(true, {}, options.items[options.startIndex || 0] || {}); const firstOpts = extend(true, {}, items[options.startIndex] || {});
options.items.forEach((item) => { items.forEach((item) => {
const $trigger = item.$trigger; const $trigger = item.$trigger;
if ($trigger) { if ($trigger) {
@ -148,9 +144,10 @@ class Fancybox extends Base {
return rez; return rez;
})(); })();
super(handleOptions(options)); super(handleOptions(items, options));
this.state = "init"; this.state = "init";
this.items = items;
this.bindHandlers(); this.bindHandlers();
@ -307,7 +304,7 @@ class Fancybox extends Base {
* @returns {Array} Slides * @returns {Array} Slides
*/ */
getSlides() { getSlides() {
const slides = [...this.options.items]; const slides = [...this.items];
slides.forEach((slide) => { slides.forEach((slide) => {
// Support items without `src`, e.g., when `data-fancybox` attribute added directly to `<img>` element // Support items without `src`, e.g., when `data-fancybox` attribute added directly to `<img>` element
@ -606,8 +603,7 @@ class Fancybox extends Base {
} }
/** /**
* Retrieve active slide * Get the active slide. This will be the first slide from the current page of the main carousel.
* This will be first slide from current page of main carousel
*/ */
getSlide() { getSlide() {
const carousel = this.Carousel; const carousel = this.Carousel;
@ -625,7 +621,7 @@ class Fancybox extends Base {
} }
/** /**
* Place focus on first focusable element inside current slide * Place focus on the first focusable element inside current slide
* @param {Event} [event] - Focus event * @param {Event} [event] - Focus event
*/ */
focus(event) { focus(event) {
@ -722,8 +718,8 @@ class Fancybox extends Base {
} }
/** /**
* Hide vertical page scrollbar and adjust `body` right padding value to prevent content from shofting * Hide vertical page scrollbar and adjust right padding value of `body` element to prevent content from shifting
* (e.g., `body` will be wider and content can expand ) * (otherwise the `body` element may become wider and the content may expand horizontally).
*/ */
hideScrollbar() { hideScrollbar() {
if (!canUseDOM) { if (!canUseDOM) {
@ -782,6 +778,7 @@ class Fancybox extends Base {
slide.$el.classList.remove(slide._className); slide.$el.classList.remove(slide._className);
} }
} }
/** /**
* Set new content for given slide * Set new content for given slide
* @param {Object} slide - Carousel slide * @param {Object} slide - Carousel slide
@ -833,7 +830,7 @@ class Fancybox extends Base {
this.manageCloseButton(slide); this.manageCloseButton(slide);
if (slide.state !== "loading") { if (slide.state !== "loading") {
this.trigger("afterLoad", slide); this.trigger("load", slide);
this.revealContent(slide); this.revealContent(slide);
} }
@ -1047,7 +1044,7 @@ class Fancybox extends Base {
} }
/** /**
* Start closing current instance * Start closing the current instance
* @param {Event} [event] - Optional click event * @param {Event} [event] - Optional click event
*/ */
close(event) { close(event) {
@ -1160,9 +1157,7 @@ class Fancybox extends Base {
* @returns {Object} Fancybox instance * @returns {Object} Fancybox instance
*/ */
static show(items, options = {}) { static show(items, options = {}) {
options.items = items; return new Fancybox(items, options);
return new Fancybox(options);
} }
/** /**
@ -1345,8 +1340,8 @@ class Fancybox extends Base {
// * Create new fancybox instance // * Create new fancybox instance
return new Fancybox( return new Fancybox(
items,
extend({}, options, { extend({}, options, {
items: items,
startIndex: index, startIndex: index,
$trigger: target, $trigger: target,
}) })
@ -1354,13 +1349,11 @@ class Fancybox extends Base {
} }
/** /**
* Add selector to opener list for basic event delegation * Attach a click handler function that starts Fancybox to the selected items, as well as to all future matching elements.
* When user clicks on the document, the script will check if click target matches any selector, * @param {String} selector - Selector that should match trigger elements
* and will start Fancybox if one is found * @param {Object} [options] - Custom options
* @param {String} opener - Selector that should match trigger elements
* @param {Object} options - Custom options
*/ */
static assign(opener, options = {}) { static bind(selector, options = {}) {
if (!canUseDOM) { if (!canUseDOM) {
return; return;
} }
@ -1378,15 +1371,15 @@ class Fancybox extends Base {
} }
} }
Fancybox.openers.set(opener, options); Fancybox.openers.set(selector, options);
} }
/** /**
* Remove selector from the the opener list * Remove the click handler that was attached with `bind()`
* @param {String} opener - Selector * @param {String} selector - A selector which should match the one originally passed to .bind()
*/ */
static trash(opener) { static unbind(selector) {
Fancybox.openers.delete(opener); Fancybox.openers.delete(selector);
if (!Fancybox.openers.size) { if (!Fancybox.openers.size) {
Fancybox.destroy(); Fancybox.destroy();
@ -1394,16 +1387,22 @@ class Fancybox extends Base {
} }
/** /**
* Clean up bindings * Immediately destroy all instances (without closing animation) and clean up all bindings..
*/ */
static destroy() { static destroy() {
let fb;
while ((fb = Fancybox.getInstance())) {
fb.destroy();
}
Fancybox.openers = new Map(); Fancybox.openers = new Map();
document.body.removeEventListener("click", Fancybox.fromEvent, false); document.body.removeEventListener("click", Fancybox.fromEvent, false);
} }
/** /**
* Returns instance by identifier or the top most instance, if identifier is not provided * Retrieve instance by identifier or the top most instance, if identifier is not provided
* @param {String|Numeric} [id] - Optional instance identifier * @param {String|Numeric} [id] - Optional instance identifier
*/ */
static getInstance(id) { static getInstance(id) {
@ -1427,7 +1426,7 @@ class Fancybox extends Base {
} }
/** /**
* Close currently active instances * Close all or topmost currently active instance.
* @param {boolean} [all] - All or only topmost active instance * @param {boolean} [all] - All or only topmost active instance
*/ */
static close(all = true) { static close(all = true) {
@ -1458,6 +1457,6 @@ Fancybox.isMobile = () =>
navigator ? /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) : false; navigator ? /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) : false;
// Auto init with default options // Auto init with default options
Fancybox.assign("[data-fancybox]"); Fancybox.bind("[data-fancybox]");
export { Fancybox }; export { Fancybox };

13
src/Fancybox/l10n/de.js

@ -2,12 +2,11 @@ export default {
CLOSE: "Schlie&szlig;en", CLOSE: "Schlie&szlig;en",
NEXT: "Weiter", NEXT: "Weiter",
PREV: "Zur&uuml;ck", PREV: "Zur&uuml;ck",
MODAL: "Sie können diesen modalen Inhalt mit der ESC-Taste schließen",
ERROR: "Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es sp&auml;ter nochmal.", ERROR: "Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es sp&auml;ter nochmal.",
PLAY_START: "Diaschau starten", IMAGE_ERROR: "Bild nicht gefunden",
PLAY_STOP: "Diaschau beenden", ELEMENT_NOT_FOUND: "HTML-Element nicht gefunden",
FULL_SCREEN: "Vollbild", AJAX_NOT_FOUND: "Fehler beim Laden von AJAX: Nicht gefunden",
THUMBS: "Vorschaubilder", AJAX_FORBIDDEN: "Fehler beim Laden von AJAX: Verboten",
DOWNLOAD: "Herunterladen", IFRAME_ERROR: "Fehler beim Laden der Seite",
SHARE: "Teilen",
ZOOM: "Vergr&ouml;&szlig;ern",
}; };

6
src/Fancybox/plugins/Html/Html.js

@ -78,7 +78,7 @@ export class Html {
* Check if each gallery item has type when fancybox starts * Check if each gallery item has type when fancybox starts
*/ */
onPrepare() { onPrepare() {
this.fancybox.options.items.forEach((slide) => { this.fancybox.items.forEach((slide) => {
this.processType(slide); this.processType(slide);
}); });
} }
@ -102,6 +102,10 @@ export class Html {
let type = slide.type || this.fancybox.options.type, let type = slide.type || this.fancybox.options.type,
rez = null; rez = null;
if (src && typeof src !== "string") {
return;
}
if ( if (
(rez = src.match( (rez = src.match(
/(?:youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(?:watch\?(?:.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(?:.*)|[\w-]{11}|\?listType=(?:.*)&list=(?:.*))(?:.*)/i /(?:youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(?:watch\?(?:.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(?:.*)|[\w-]{11}|\?listType=(?:.*)&list=(?:.*))(?:.*)/i

12
src/Fancybox/plugins/Image/Image.js

@ -27,13 +27,13 @@ const defaults = {
ignoreCoveredThumbnail: false, ignoreCoveredThumbnail: false,
// Action to be performed when user clicks on the image // Action to be performed when user clicks on the image
click: "toggleZoom", // "toggleZoom" | "next" | "close" click: "toggleZoom", // "toggleZoom" | "next" | "close" | null
// Action to be performed when double-click event is detected on the image // Action to be performed when double-click event is detected on the image
doubleClick: "", // "toggleZoom" doubleClick: null, // "toggleZoom" | null
// Action to be performed when user rotates a wheel button on a pointing device // Action to be performed when user rotates a wheel button on a pointing device
wheel: "zoom", // "zoom" | "slide" | "close" wheel: "zoom", // "zoom" | "slide" | "close" | null
// How image should be resized to fit its container // How image should be resized to fit its container
fit: "contain", // "contain" | "contain-w" | "cover" fit: "contain", // "contain" | "contain-w" | "cover"
@ -195,9 +195,9 @@ export class Image {
panOnlyZoomed: true, panOnlyZoomed: true,
// Disable default click/wheel events; custom callbacks will replace them // Disable default click/wheel events; custom callbacks will replace them
click: false, click: null,
doubleClick: false, doubleClick: null,
wheel: false, wheel: null,
on: { on: {
afterAnimate: (panzoom) => { afterAnimate: (panzoom) => {

5
src/Fancybox/plugins/Thumbs/Thumbs.js

@ -2,8 +2,11 @@ import { extend } from "../../../shared/utils/extend.js";
import { Carousel } from "../../../Carousel/Carousel.js"; import { Carousel } from "../../../Carousel/Carousel.js";
const defaults = { const defaults = {
// Automatically show thumbnails when opened
autoStart: true, autoStart: true,
// The minimum number of images in the gallery to display thumbnails
minSlideCount: 3, minSlideCount: 3,
// Keyboard shortcut to toggle thumbnail container
key: "t", key: "t",
}; };
@ -121,7 +124,7 @@ export class Thumbs {
getSlides() { getSlides() {
const slides = []; const slides = [];
this.fancybox.options.items.forEach((slide) => { this.fancybox.items.forEach((slide) => {
const thumb = slide.thumb; const thumb = slide.thumb;
if (thumb) { if (thumb) {

7
src/Panzoom/plugins/Controls/Controls.scss

@ -1,12 +1,12 @@
.panzoom__controls { .panzoom__controls {
position: absolute; position: absolute;
bottom: 16px; top: 16px;
right: 16px; left: 16px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
transform-origin: bottom right; transform-origin: top left;
transform: scale(0.75); transform: scale(0.75);
} }
@ -15,6 +15,7 @@
margin: 0; margin: 0;
padding: 10px; padding: 10px;
border: 0; border: 0;
border-radius: 0;
color: #222; color: #222;
background: #eee; background: #eee;

Loading…
Cancel
Save