Select image with a preview 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: select image with preview</h1>

<div id="btn" class="btn btn-primary" style="opacity:0.2;cursor:default">Select image...</div>
<div id="loading" style="font-size:12px">Loading file manager...</div>

<h2 class="h5 mt-5">Selected image</h2>

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

<div id="images">
  No image selected yet.
</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 {Luminous} 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 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();
    });
}

function selectFiles() {
  Flmngr.open({
    createImageFormats: ["preview"],
    acceptExtensions: ["png", "jpeg", "jpg", "webp", "gif"],
    isMultiple: false,
    onFinish: (files) => {
      showSelectedImageWithPreview(files);
    }
  });
}

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

  // As far we requested just one file, it is the only item of the array
  let file = files[0];
  let filePreview = file.formats.find(file => file.format === "preview");
  let urlPreview = Flmngr.getNoCacheUrl(filePreview.url);
  let urlOriginal = Flmngr.getNoCacheUrl(file.url)

  // Add preview image
  let elTextPreview = document.createElement("p");
  elTextPreview.textContent = "Preview image";
  elImages.appendChild(elTextPreview);

  let elImgPreview = document.createElement("img");

  elImgPreview.src = urlPreview;
  elImgPreview.alt = "Image preview selected in Flmngr";
  elImgPreview.setAttribute("data-src-original", urlOriginal);
  elImages.appendChild(elImgPreview);
  attachLightBoxToImage(elImgPreview);

  // Add image original
  let elText = document.createElement("p");
  elText.textContent = "Original image";
  elImages.appendChild(elText);

  let elImg = document.createElement("img");
  elImg.src = urlOriginal;
  elImg.alt = "Image selected in Flmngr";
  elImages.appendChild(elImg);

  document.getElementById("hint").style.display = "block";
}

function attachLightBoxToImage(elImg) {
  new Luminous(
    elImg,
    {
      "showCloseButton": true,
      "sourceAttribute": "data-src-original",
    }
  );
}
body {
  padding: 20px;
  background-color: #F4F4F4;
}

#images p {
  margin: 5px 0 0 0;
  font-size: 14px;
  color: #444;
}
#images img[data-src-original] {
  cursor: pointer;
  border: 2px solid #007FFF;
}
#images img[data-src-original]:hover {
  border-color: orange;
}

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

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

You can ask the user not only to select some image from the storage (and probably upload it) but also require a preview for it.

After passing the required parameters into the file manager, it will automatically generate previews for selected files using the maximum width and/or height you specified.

To implement this you need to define imageFormats parameter. It should be passed in any method you use (or just to Flmngr.load({params}) if you use preloading of the library. There are two image formats already defined by default (preview and medium), but you might want to change their maxWidth/maxHeight or add new formats.

So when passed into Flmngr.open({params}) it will explain to Flmngr that there are some image formats it should support. First of all the file manager will group all image formats (image variants) in one preview.

Now to ask the file manager to return both the original image and image preview you must refer to the IDs of defined imageFormats in a createImageFormats parameter. The original image is returned always but also list in this parameter formats you need to be returned when user picked an image or images.

It will work with isMultiple is to true - this is useful for managing galleries.

Inside onFinish callback you'll receive a structure like this (if you asked to generate a preview format):

[
    {
        url: "http://example.com/files/selected-image.png",
        formats: [
            {
                format: "preview"
                url: "http://example.com/files/selected-image-preview.png",
            }
        ]
    }
]

The final code will be:

NPM

React

Snippet

TinyMCE

CKEditor 4

CKEditor 5

import Flmngr from "flmngr";

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
    isMultiple: false,                                   // let selecting a single file
    onFinish: (files) => {
        // Selected image (isMultiple == false returns always a single file)
        let file = files[0];
        console.log("Original image: " + file.url);

        // Automatically generated preview
        let filePreview = file.formats.find((f) => { 
            return f.format === "preview"; 
        });
        console.log("Preview image: " + filePreview.url);
    }
});
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
                    isMultiple: false,                                   // let selecting a single file
                    onFinish: (files) => {
                        // Selected image (isMultiple == false returns always a single file)
                        let file = files[0];
                        console.log("Original image: " + file.url);

                        // Automatically generated preview
                        let filePreview = file.formats.find((f) => { 
                            return f.format === "preview"; 
                        });
                        console.log("Preview image: " + filePreview.url);
                    }
                });

            }}
        >
            Open file manager
        </button>
    }

}
<script src="https://unpkg.com/flmngr"></script>
<script>
    window.onFlmngrAPILoaded = function() {
        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
            isMultiple: false,                                   // let selecting a single file
            onFinish: (files) => {
                // Selected image (isMultiple == false returns always a single file)
                let file = files[0];
                console.log("Original image: " + file.url);

                // Automatically generated preview
                let filePreview = file.formats.find((f) => { 
                    return f.format === "preview"; 
                });
                console.log("Preview image: " + filePreview.url);
            }
        });
    }
</script>
// TinyMCE was initialized somewhere before
tinymce.activeEditor.getFlmngr(
    (Flmngr) => {
        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
            isMultiple: false,                                   // let selecting a single file
            onFinish: (files) => {
                // Selected image (isMultiple == false returns always a single file)
                let file = files[0];
                console.log("Original image: " + file.url);

                // Automatically generated preview
                let filePreview = file.formats.find((f) => { 
                    return f.format === "preview"; 
                });
                console.log("Preview image: " + filePreview.url);
            }
        });
    }
);
// CKEditor was initialized somewhere before
CKEDITOR.instances["editor"].getFlmngr(
    (Flmngr) => {
        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
            isMultiple: false,                                   // let selecting a single file
            onFinish: (files) => {
                // Selected image (isMultiple == false returns always a single file)
                let file = files[0];
                console.log("Original image: " + file.url);

                // Automatically generated preview
                let filePreview = file.formats.find((f) => { 
                    return f.format === "preview"; 
                });
                console.log("Preview image: " + filePreview.url);
            }
        });
    }
);
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) => {
                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
                    isMultiple: false,                                   // let selecting a single file
                    onFinish: (files) => {
                        // Selected image (isMultiple == false returns always a single file)
                        let file = files[0];
                        console.log("Original image: " + file.url);

                        // Automatically generated preview
                        let filePreview = file.formats.find((f) => { 
                            return f.format === "preview"; 
                        });
                        console.log("Preview image: " + filePreview.url);
                    }
                });
            }
        );
    } 
).catch((error) => {});