Open image editor directly from JavaScript code

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 2: edit and save image</h1>

<p>
  <img id="image" style="max-width:500px" src="https://fm.n1ed.com/files/paper.png" alt="Some image">
</p>

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

<script src="https://cloud.n1ed.com/cdn/CPENDFLT/n1flmngr.js"></script>
<script src="https://cloud.n1ed.com/cdn/CPENDFLT/n1imgpen.js"></script>
window.onFlmngrAndImgPenLoaded = function() {

  var elBtn = document.getElementById("btn");

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

  // Add a listener for editing currently shown image
  elBtn.addEventListener("click", function() {
    editImage();
  });
}

function editImage() {

  // Create an instance object of flmngr, can be reused
  let flmngr = window.flmngr.create({
    urlFileManager: 'https://fm.n1ed.com/fileManager',
    urlFiles: 'https://fm.n1ed.com/files'
  });

  flmngr.editImageAndUpload({
    url: decodeURI(document.getElementById("image").getAttribute("src")),
    onSave: function(urlNew) {

      animateLoading();

      // Image edited, saved and uploaded to server: change the image
      // `getNoCacheUrl` will add `?no-cache=time` parameter to force image reloading in the browser
      var elImg = document.getElementById("image");
      elImg.setAttribute("src", flmngr.getNoCacheUrl(urlNew));

    },
    onFail: function(error) {
      alert("Error: " + error);
    }
  });
}

// Just for animating image while it is being reloading after change
function animateLoading() {
  var elImg = document.getElementById("image");
  var onLoaded = function() {
    elImg.classList.remove("loading");
    elImg.removeEventListener("click", onLoaded);
  }
  elImg.classList.add("loading");
  elImg.addEventListener("load", onLoaded);
}
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: 350px;
  border: 1px solid #DDD;
}
#images .image p {
  margin: 5px 0 0 0;
  font-size: 14px;
  color: #444;
}

@-webkit-keyframes loading-animation {
  50% {
    opacity: 0.3;
  }
}
@keyframes loading-animation {
  50% {
    opacity: 0.3;
  }
}
.loading {
  animation: loading-animation 1s infinite;
}

ImgPen image editor is built into Flmngr file manager and in most of cases you do not need to call it manually due to its button is already inside the file manager select files dialog - user will open the image editor from there, edit an image and save it back to the server.

But when you need to call image editor outside of file manager context, you can do it using Flmngr API.

With such API and its Flmngr.editAndUpload({params}) method you can call image editor with image from your storage or outside of it, and then save the result image into your storage. The parameter url and the callback onSave(urlNew) will help you with this task.

If you do not need to save edited image in the storage at the same moment, there are atomic Flmngr.edit({params}) and Flmngr.upload({params}) methods, and there is a separate sample of their usage.

This sample uses Flmngr.getNoCacheUrl() method to add ?no-cache=time suffix to the new URL because if user saved a new image by rewriting the existing one, browser will not refresh (reload) an image already existed on the page until you refresh whole the page - this is a feature of all browsers. Fortunately, Flmngr API has the method to bypass this pitfall.

NPM

React

Snippet

TinyMCE

CKEditor 4

CKEditor 5

import Flmngr from "flmngr";

let elImg = document.getElementById("img"); // your own image

Flmngr.editImageAndUpload({
    apiKey: "FLMNFLMN",                                  // default free key
    urlFileManager: 'https://fm.flmngr.com/fileManager', // demo server
    urlFiles: 'https://fm.flmngr.com/files',             // demo file storage
    url: elImg.src,                                      // insert your own
    onSave: function(urlNew) {
        // Do anything you want with the new image 
        elImg.setAttribute("src", Flmngr.getNoCacheUrl(urlNew));
    }
});
import Flmngr from "@flmngr/flmngr-react";
import * as React from "react";

export class MyButton extends React.Component {

    render() {
        return <button 
            onClick={() => {
                Flmngr.editImageAndUpload({
                    apiKey: "FLMNFLMN",                                  // default free key
                    urlFileManager: 'https://fm.flmngr.com/fileManager', // demo server
                    urlFiles: 'https://fm.flmngr.com/files',             // demo file storage
                    url: this.state.urlImage,                            // insert your own
                    onSave: function(urlNew) {
                        // Do anything you want with the new image
                        this.setState({
                            urlImage: Flmngr.getNoCacheUrl(urlNew) 
                        });
                    }
                });
            }}
        >
            Edit image
        </button>
    }

}
<script src="https://unpkg.com/flmngr"></script>
<script>
    window.onFlmngrAPILoaded = function() {

        let elImg = document.getElementById("img"); // your own image

        Flmngr.editImageAndUpload({
            apiKey: "FLMNFLMN",                                  // default free key
            urlFileManager: 'https://fm.flmngr.com/fileManager', // demo server
            urlFiles: 'https://fm.flmngr.com/files',             // demo file storage
            url: elImg.src,                                      // insert your own
            onSave: function(urlNew) {
                // Do anything you want with the new image 
                elImg.setAttribute("src", Flmngr.getNoCacheUrl(urlNew));
            }
        });
    }
</script>
// TinyMCE was initialized somewhere before
tinymce.activeEditor.getFlmngr(
    (Flmngr) => {
        Flmngr.open({
            // Do not specify here 'apiKey', 'urlFileManager' and 'urlFiles' again
            // (they were passed in initialization code)
            isMultiple: false,  // let selecting a single file
            acceptExtensions: ["png", "jpg", "jpeg", "gif", "webp"],
            onFinish: (files) => {
                console.log("User picked:");
                console.log(files);
            }
        });
    }
);
// CKEditor was initialized somewhere before
CKEDITOR.instances["editor"].getFlmngr(
    (Flmngr) => {
        Flmngr.open({
            // Do not specify here 'apiKey', 'urlFileManager' and 'urlFiles' again
            // (they were passed in initialization code or in 'config.js')
            isMultiple: false,  // let selecting a single file
            acceptExtensions: ["png", "jpg", "jpeg", "gif", "webp"],
            onFinish: (files) => {
                console.log("User picked:");
                console.log(files);
            }
        });
    }
);
ClassicEditor.create(
    document.querySelector('#editorId'), 
    {
        Flmngr: {
            apiKey: "FLMNFLMN",                                  // default free key
            urlFileManager: 'https://fm.flmngr.com/fileManager', // demo server
            urlFiles: 'https://fm.flmngr.com/files',             // demo file storage
        }
    } 
).then( 
    (editor) => {
        editor.getFlmngr(
            (Flmngr) => {
                let elImg = document.getElementById("img"); // your own image

                Flmngr.editImageAndUpload({
                    // There is no need to set 'apiKey', 'urlFileManager' or 'urlFiles' here
                    // due to you already set them in the config of CKEditor.
                    url: elImg.src,                                      // insert your own
                    onSave: function(urlNew) {
                        // Do anything you want with a new image 
                        elImg.setAttribute("src", Flmngr.getNoCacheUrl(urlNew));
                    }
                });
            }
        );
    } 
).catch((error) => {});