Manage image gallery with file manager

This sample demonstrates a usage of a new Flmngr API. The sample of legacy API usage can be found here.

Play on CodePen External link All samples on CodePen External link

Demo
HTML
JavaScript
CSS
<h1 class="h5 mb-3">Flmngr file manager: manage image gallery</h1>

<div id="btn" class="btn btn-primary" style="opacity:0.2;cursor:default">Manage gallery...</div>
<div id="loading" style="font-size:12px">Loading file manager...</div>
<p class="hint"><b>Hint</b>: after you selected gallery images,<br/> you can re-manage the existing gallery.</p>

<h2 class="h5 mt-5">Image gallery</h2>

<p id="hint" style="display:none" class="hint"><b>Hint</b>: the previews are clickable.</p>

<div id="images">
  <p>0 images selected</p>
</div>
// In real app replace with:
// import Flmngr from "flmngr";
import Flmngr from "https://cdn.skypack.dev/flmngr";

// This demo uses a script for animating showing full-screen image when user clicks on a preview (a-la LightBox)
import {LuminousGallery} from "https://cdn.skypack.dev/luminous-lightbox@2.4.0";

Flmngr.load({
  apiKey: "FLMNFLMN",
  urlFileManager: 'https://fm.n1ed.com/fileManager',
  urlFiles: 'https://fm.n1ed.com/files',
  imageFormats: [
     {
        id: "preview",
        title: "Preview",
        suffix: "-preview",
        maxWidth: 250,
        maxHeight: 250
     }
  ]
}, {
  onFlmngrLoaded: () => {
    attachOnClickListenerToButton();
  }
});

function selectFiles() {

  // Collect URLs of images of existing gallery set
  let elsExistingImages = document.querySelectorAll(".image > img");
  let urls = [];
  for (let i=0; i<elsExistingImages.length; i++)
    urls.push(elsExistingImages.item(i).src);

  Flmngr.open({
    list: urls,
    isMultiple: true,
    acceptExtensions: ["png", "jpeg", "jpg", "webp", "gif"],
    createImageFormats: ["preview"],
    onFinish: (files) => {
      showSelectedImages(files);
    }
  });
}

function showSelectedImages(files) {
  let elImages = document.getElementById("images");
  elImages.innerHTML = "";

  let elP =  document.createElement("p");
  elP.textContent = files.length + " images selected";
  elImages.appendChild(elP);

  for (let file of files) {

    let filePreview = file.formats.find(file => file.format === "preview");
  let urlPreview = Flmngr.getNoCacheUrl(filePreview.url);
  let urlOriginal = Flmngr.getNoCacheUrl(file.url)

    let el = document.createElement("div");
    el.className = "image";
    elImages.appendChild(el);   

    let elImg = document.createElement("img");
    elImg.src = urlPreview;
    elImg.alt = "Image selected in Flmngr";
    elImg.setAttribute("data-src-original", urlOriginal);
    el.appendChild(elImg);

    let elP = document.createElement("p");
    elP.textContent = file.url;
    el.appendChild(elP);

  }        

  attachLightBoxToGallery();
}

function attachLightBoxToGallery() {

  let elsPreviews = document.querySelectorAll(".image > img");

  document.getElementById("hint").style.display = elsPreviews.length > 0 ? "block" : "none";

  elsPreviews.forEach(el => {
    if (!el.hasAttribute("data-src-original"))
      el.setAttribute("data-src-original", el.getAttribute("src"));
  });

  new LuminousGallery(
    elsPreviews,
    {
      "arrowNavigation": true
    },
    {
      "showCloseButton": true,
      "sourceAttribute": "data-src-original",
    }
  );
}

function attachOnClickListenerToButton() {
  let elBtn = document.getElementById("btn");

  // Style button as ready to be pressed
  elBtn.style.opacity = 1;
  elBtn.style.cursor = "pointer";
  let elLoading = document.getElementById("loading");
  elLoading.parentElement.removeChild(elLoading);

  // Add a listener for selecting files
  elBtn.addEventListener("click", () => {
    selectFiles();
  });
}
body {
  padding: 20px;
  background-color: #F4F4F4;
}

#images .image {
  border: 1px solid #DDD;
  box-shadow: 5px 5px 0 0 #DDD;
  background-color: white;
  padding: 10px;
  display: inline-flex;
  flex-direction: column;
  margin: 0 25px 25px 0;
}
#images .image img {
  max-height: 250px;
  cursor: pointer;
  border: 2px solid #007FFF;
}
#images .image img:hover {
  border-color: orange;
}
#images .image p {
  margin: 5px 0 0 0;
  font-size: 14px;
  color: #444;
}

.lum-img {
  cursor: zoom-out;
  max-width: 100vw !important;
  max-height: 100vh !important;
}

.lum-lightbox {
  z-index: 1000;
  cursor: zoom-out;
}

.lum-lightbox-inner img {
  margin: 0 auto;
}

.lum-lightbox-image-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}

.lum-close-button {
  cursor: pointer;
}

.lum-lightbox-image-wrapper {
  background: rgba(0, 0, 0, 0.7);
}

.hint {
  color: #007FFF;
  font-size: 14px;
  margin-top: 10px;
  line-height: 16px;
}

One of the popular tasks is selecting multiple images and modifying a selected list of images from time to time. This means you need to open the file manager dialog with preselected images that are a part of the existing gallery.

So you will need to open the file manager but with the option isMultiple set to true and need to generate previews for selected images. Also, you need to specify the list parameter - URLs of images if there are some images in the gallery you edit.

NPM

React

Snippet

TinyMCE

CKEditor 4

CKEditor 5

import Flmngr from "flmngr";

// Get all images that currently exist in a gallery
let urls = getGalleryImages(); // your code

Flmngr.open({
    apiKey: "FLMN24RR1234123412341234",                  // default free key
    urlFileManager: 'https://fm.flmngr.com/fileManager', // demo server
    urlFiles: 'https://fm.flmngr.com/files',             // demo file storage
    imageFormats: [                                      // define image formats
        {
            id: "preview",
            title: "Preview",
            suffix: "-preview",
            maxWidth: 250,
            maxHeight: 250
        }
    ],
    createImageFormats: ["preview"],                     // return these format IDs
    acceptExtensions: ["png", "jpeg", "jpg", "webp"],    // accept images only
    list: urls,                                          // preselected images
    isMultiple: false,                                   // let selecting a single file
    onFinish: (files) => {
        setGalleryImages(files); // your code
    }
});
import Flmngr from "@flmngr/flmngr-react";
import * as React from "react";

export class MyButton extends React.Component {

    render() {
        return <button 
            onClick={() => {

                Flmngr.open({
                    apiKey: "FLMN24RR1234123412341234",                  // default free key
                    urlFileManager: 'https://fm.flmngr.com/fileManager', // demo server
                    urlFiles: 'https://fm.flmngr.com/files',             // demo file storage
                    imageFormats: [                                      // define image formats
                        {
                            id: "preview",
                            title: "Preview",
                            suffix: "-preview",
                            maxWidth: 250,
                            maxHeight: 250
                        }
                    ],
                    createImageFormats: ["preview"],                     // return these format IDs
                    acceptExtensions: ["png", "jpeg", "jpg", "webp"],    // accept images only
                    list: this.state.urlsGallery,                        // preselected images
                    isMultiple: false,                                   // let selecting a single file
                    onFinish: (files) => {
                        let previews = files.map(file => file.formats.find(f => f.format === 'preview'));
                        this.setState({
                            urlsGallery: files.map(file => file.url)
                            urlsGalleryPreviews: previews.map(file => file.url)
                        });
                        setGalleryImages(files); // your code
                    }
                });

            }}
        >
            Open file manager
        </button>
    }

}
<script src="https://unpkg.com/flmngr"></script>
<script>
    window.onFlmngrAPILoaded = function() {
        // Get all images that currently exist in a gallery
        let urls = getGalleryImages(); // your code

        Flmngr.open({
            apiKey: "FLMN24RR1234123412341234",                  // default free key
            urlFileManager: 'https://fm.flmngr.com/fileManager', // demo server
            urlFiles: 'https://fm.flmngr.com/files',             // demo file storage
            imageFormats: [                                      // define image formats
                {
                    id: "preview",
                    title: "Preview",
                    suffix: "-preview",
                    maxWidth: 250,
                    maxHeight: 250
                }
            ],
            createImageFormats: ["preview"],                     // return these format IDs
            acceptExtensions: ["png", "jpeg", "jpg", "webp"],    // accept images only
            list: urls,                                          // preselected images
            isMultiple: false,                                   // let selecting a single file
            onFinish: (files) => {
                setGalleryImages(files); // your code
            }
        });
    }
</script>
// TinyMCE was initialized somewhere before
tinymce.activeEditor.getFlmngr(
    (Flmngr) => {
        // Get all images that currently exist in a gallery
        let urls = getGalleryImages(); // your code

        Flmngr.open({
            // Do not specify here 'apiKey', 'urlFileManager', 'urlFiles'
            // and 'imageFormats' again (they were passed in TinyMCE initialization code)
            createImageFormats: ["preview"],                     // return these format IDs
            acceptExtensions: ["png", "jpeg", "jpg", "webp"],    // accept images only
            list: urls,                                          // preselected images
            isMultiple: false,                                   // let selecting a single file
            onFinish: (files) => {
                setGalleryImages(files); // your code
            }
        });
    }
);
// CKEditor was initialized somewhere before
CKEDITOR.instances["editor"].getFlmngr(
    (Flmngr) => {
        // Get all images that currently exist in a gallery
        let urls = getGalleryImages(); // your code

        Flmngr.open({
            // Do not specify here 'apiKey', 'urlFileManager', 'urlFiles'
            // and 'imageFormats' again (they were passed in CKEditor initialization 
            // code or in 'config.js')
            createImageFormats: ["preview"],                     // return these format IDs
            acceptExtensions: ["png", "jpeg", "jpg", "webp"],    // accept images only
            list: urls,                                          // preselected images
            isMultiple: false,                                   // let selecting a single file
            onFinish: (files) => {
                setGalleryImages(files); // your code
            }
        });
    }
);
ClassicEditor.create(
    document.querySelector('#editorId'), 
    {
        Flmngr: {
            apiKey: "FLMN24RR1234123412341234",                  // default free key
            urlFileManager: 'https://fm.flmngr.com/fileManager', // demo server
            urlFiles: 'https://fm.flmngr.com/files',             // demo file storage
            imageFormats: [                                      // define image formats
                {
                    id: "preview",
                    title: "Preview",
                    suffix: "-preview",
                    maxWidth: 250,
                    maxHeight: 250
                }
            ],
        }
    } 
).then( 
    (editor) => {
        editor.getFlmngr(
            (Flmngr) => {
                // Get all images that currently exist in a gallery
                let urls = getGalleryImages(); // your code

                Flmngr.open({
                    // There is no need to set 'apiKey', 'urlFileManager', 'urlFiles' or
                    // 'imagePreviews' here due to you already set them in the config of CKEditor.
                    createImageFormats: ["preview"],                     // return these format IDs
                    acceptExtensions: ["png", "jpeg", "jpg", "webp"],    // accept images only
                    list: urls,                                          // preselected images
                    isMultiple: false,                                   // let selecting a single file
                    onFinish: (files) => {
                        setGalleryImages(files); // your code
                    }
                });
            }
        );
    } 
).catch((error) => {});

Manage image gallery