When to use

The image editor is built into the Flmngr file manager, and in most cases you do not need to call it manually because its button is already inside the file manager's select files dialog — the user opens the image editor from there, edits an image, and saves it back to the server.

However, when you need to call the image editor outside of the file manager context, you can do that as well.

By default, as shown in this sample, it allows you to edit an image and then save it back to the storage — either by overwriting the old image or creating a copy, with a dialog for that. In another sample, you can see how to edit an image without uploading it.

How it works

There is an API method Flmngr.editAndUpload({params}) that opens the image editor for a specified image from your storage or outside of it, and then saves the resulting image into your storage. The url parameter and the callback onSave(urlNew) are crucial here.

This method is a simple but powerful combination of the atomic Flmngr.edit({params}) and Flmngr.upload({params}) methods, plus a save dialog that helps handle file renaming, overwriting, and JPEG optimization.

Additionally, this sample uses the Flmngr.getNoCacheUrl() method to add a ?no-cache=time suffix to the new URL. If the user saved a new image by overwriting the existing one, the browser will not refresh (reload) the image already present on the page until the whole page is refreshed — this is standard browser behavior. Fortunately, this Flmngr API method helps to bypass this issue.

How to start using

Use this code in a custom application when you install the React file manager component or the JavaScript file manager package from NPM.

If your app doesn't use NPM at all, you can quickly install the file manager JS snippet instead.

These packages provide a powerful Flmngr API, which this and other code samples demonstrate.

Demo
Code
HTML
CSS
import {Flmngr} from "flmngr";

Flmngr.load({
  apiKey: "FLMN24RR1234123412341234",
  urlFileManager: 'https://fm.flmngr.com/fileManager',
  urlFiles: 'https://fm.flmngr.com/files'
}, {
  onImgPenLoaded: () => {
    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 editing currently shown image
  elBtn.addEventListener("click", () => {
    editImage();
  });
}

function editImage() {
  
  Flmngr.edit({
    url: decodeURI(document.getElementById("image").getAttribute("src")),
    
    onSave: (onExport, onClose) => {
      // You can use "onExport" function to export the canvas as many times as you need.
      // Call "onClose" function to close the image editor.
      onExport(
        "new_name",
        "jpg",
        95,
        (imageBlob) => {
        
          // Convert image (Blob object) into Base64
          let reader = new FileReader();
          reader.onloadend = () => {
            let base64 = reader.result;                
            
            // Append a new image onto the document
            let elImg = document.getElementById("image");
            let elImgNew = document.createElement("img");
            elImgNew.src = base64;
            elImg.parentElement.appendChild(elImgNew); 
            
            onClose();
          }
          reader.readAsDataURL(imageBlob); 
        
        }
      );
      
    },
    onFail: (error) => {
      alert("Error: " + error);
    }
  });
}
<h2 class="mb-3">Flmngr: Edit Image and Save as Base64</h2>

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

<p>
  <img id="image" src="https://fm.n1ed.com/files/paper.png" alt="Some image">
</p>
body {
  padding: 20px;
  background-color: #F4F4F4;
}

h2 {
  font-weight: bold;
}

img {
  max-width:500px;
}

p {
  margin-top: 20px;
}

@-webkit-keyframes loading-animation {
  50% {opacity: 0.3;}
}

@keyframes loading-animation {
  50% {opacity: 0.3;}
}

.loading {
  animation: loading-animation 1s infinite;
}