mirror of
https://github.com/Ionaru/easy-markdown-editor
synced 2025-07-13 04:54:28 -06:00
Allow custom upload function (#106)
Allow custom upload function Co-authored-by: Jeroen Akkerman <Jeroen_akkerman1@hotmail.com>
This commit is contained in:
commit
eb59b22491
@ -152,11 +152,13 @@ easyMDE.value('New input for **EasyMDE**');
|
|||||||
- **uploadImage**: If set to `true`, enables the image upload functionality, which can be triggered by drag&drop, copy-paste and through the browse-file window (opened when the user click on the *upload-image* icon). Defaults to `false`.
|
- **uploadImage**: If set to `true`, enables the image upload functionality, which can be triggered by drag&drop, copy-paste and through the browse-file window (opened when the user click on the *upload-image* icon). Defaults to `false`.
|
||||||
- **imageMaxSize**: Maximum image size in bytes, checked before upload (note: never trust client, always check image size at server-side). Defaults to `1024*1024*2` (2Mb).
|
- **imageMaxSize**: Maximum image size in bytes, checked before upload (note: never trust client, always check image size at server-side). Defaults to `1024*1024*2` (2Mb).
|
||||||
- **imageAccept**: A comma-separated list of mime-types used to check image type before upload (note: never trust client, always check file types at server-side). Defaults to `image/png, image/jpeg`.
|
- **imageAccept**: A comma-separated list of mime-types used to check image type before upload (note: never trust client, always check file types at server-side). Defaults to `image/png, image/jpeg`.
|
||||||
|
- **imageUploadFunction**: A custom function for handling the image upload. Using this function will render the options `imageMaxSize`, `imageAccept`, `imageUploadEndpoint` and `imageCSRFToken` ineffective.
|
||||||
|
- The function gets a file and onSuccess and onError callback functions as parameters. `onSuccess(imageUrl: string)` and `onError(errorMessage: string)`
|
||||||
- **imageUploadEndpoint**: The endpoint where the images data will be sent, via an asynchronous *POST* request. The server is supposed to save this image, and return a json response.
|
- **imageUploadEndpoint**: The endpoint where the images data will be sent, via an asynchronous *POST* request. The server is supposed to save this image, and return a json response.
|
||||||
- if the request was successfully processed (HTTP 200-OK): `{"data": {"filePath": "<filePath>"}}` where *filePath* is the relative path of the image;
|
- if the request was successfully processed (HTTP 200-OK): `{"data": {"filePath": "<filePath>"}}` where *filePath* is the relative path of the image;
|
||||||
- otherwise: `{"error": "<errorCode>"}`, where *errorCode* can be `noFileGiven` (HTTP 400), `typeNotAllowed` (HTTP 415), `fileTooLarge` (HTTP 413) or `importError` (see *errorMessages* below). If *errorCode* is not one of the *errorMessages*, it is alerted unchanged to the user. This allows for server side error messages.
|
- otherwise: `{"error": "<errorCode>"}`, where *errorCode* can be `noFileGiven` (HTTP 400), `typeNotAllowed` (HTTP 415), `fileTooLarge` (HTTP 413) or `importError` (see *errorMessages* below). If *errorCode* is not one of the *errorMessages*, it is alerted unchanged to the user. This allows for server side error messages.
|
||||||
No default value.
|
No default value.
|
||||||
- **imageCSRFToken**: CSRF token to include with AJAX call to upload image. For instance used with Django backend.
|
- **imageCSRFToken**: CSRF token to include with AJAX call to upload image. For instance used with Django backend.
|
||||||
- **imageTexts**: Texts displayed to the user (mainly on the status bar) for the import image feature, where `#image_name#`, `#image_size#` and `#image_max_size#` will replaced by their respective values, that can be used for customization or internationalization:
|
- **imageTexts**: Texts displayed to the user (mainly on the status bar) for the import image feature, where `#image_name#`, `#image_size#` and `#image_max_size#` will replaced by their respective values, that can be used for customization or internationalization:
|
||||||
- **sbInit**: Status message displayed initially if `uploadImage` is set to `true`. Defaults to `Attach files by drag and dropping or pasting from clipboard.`.
|
- **sbInit**: Status message displayed initially if `uploadImage` is set to `true`. Defaults to `Attach files by drag and dropping or pasting from clipboard.`.
|
||||||
- **sbOnDragEnter**: Status message displayed when the user drags a file to the text area. Defaults to `Drop image to upload it.`.
|
- **sbOnDragEnter**: Status message displayed when the user drags a file to the text area. Defaults to `Drop image to upload it.`.
|
||||||
|
@ -1640,11 +1640,19 @@ function EasyMDE(options) {
|
|||||||
this.codemirror.on('drop', function (cm, event) {
|
this.codemirror.on('drop', function (cm, event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
self.uploadImages(event.dataTransfer.files);
|
if (options.imageUploadFunction) {
|
||||||
|
self.uploadImagesUsingCustomFunction(options.imageUploadFunction, event.dataTransfer.files);
|
||||||
|
} else {
|
||||||
|
self.uploadImages(event.dataTransfer.files);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.codemirror.on('paste', function (cm, event) {
|
this.codemirror.on('paste', function (cm, event) {
|
||||||
self.uploadImages(event.clipboardData.files);
|
if (options.imageUploadFunction) {
|
||||||
|
self.uploadImagesUsingCustomFunction(options.imageUploadFunction, event.clipboardData.files);
|
||||||
|
} else {
|
||||||
|
self.uploadImages(event.clipboardData.files);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1669,6 +1677,25 @@ EasyMDE.prototype.uploadImages = function (files, onSuccess, onError) {
|
|||||||
this.updateStatusBar('upload-image', this.options.imageTexts.sbOnDrop.replace('#images_names#', names.join(', ')));
|
this.updateStatusBar('upload-image', this.options.imageTexts.sbOnDrop.replace('#images_names#', names.join(', ')));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload asynchronously a list of images to a server.
|
||||||
|
*
|
||||||
|
* Can be triggered by:
|
||||||
|
* - drag&drop;
|
||||||
|
* - copy-paste;
|
||||||
|
* - the browse-file window (opened when the user clicks on the *upload-image* icon).
|
||||||
|
* @param imageUploadFunction {Function} The custom function to upload the image passed in options.
|
||||||
|
* @param {FileList} files The files to upload the the server.
|
||||||
|
*/
|
||||||
|
EasyMDE.prototype.uploadImagesUsingCustomFunction = function (imageUploadFunction, files) {
|
||||||
|
var names = [];
|
||||||
|
for (var i = 0; i < files.length; i++) {
|
||||||
|
names.push(files[i].name);
|
||||||
|
this.uploadImageUsingCustomFunction(imageUploadFunction, files[i]);
|
||||||
|
}
|
||||||
|
this.updateStatusBar('upload-image', this.options.imageTexts.sbOnDrop.replace('#images_names#', names.join(', ')));
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update an item in the status bar.
|
* Update an item in the status bar.
|
||||||
* @param itemName {string} The name of the item to update (ie. 'upload-image', 'autosave', etc.).
|
* @param itemName {string} The name of the item to update (ie. 'upload-image', 'autosave', etc.).
|
||||||
@ -2058,6 +2085,42 @@ EasyMDE.prototype.uploadImage = function (file, onSuccess, onError) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload an image to the server using a custom upload function.
|
||||||
|
*
|
||||||
|
* @param imageUploadFunction {Function} The custom function to upload the image passed in options
|
||||||
|
* @param file {File} The image to upload, as a HTML5 File object (https://developer.mozilla.org/en-US/docs/Web/API/File).
|
||||||
|
*/
|
||||||
|
EasyMDE.prototype.uploadImageUsingCustomFunction = function(imageUploadFunction, file) {
|
||||||
|
var self = this;
|
||||||
|
function onSuccess(imageUrl) {
|
||||||
|
afterImageUploaded(self, imageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onError(errorMessage) {
|
||||||
|
var filledErrorMessage = fillErrorMessage(errorMessage);
|
||||||
|
// show error on status bar and reset after 10000ms
|
||||||
|
self.updateStatusBar('upload-image', filledErrorMessage);
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
self.updateStatusBar('upload-image', self.options.imageTexts.sbInit);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
// run error handler from options, this alerts the message.
|
||||||
|
self.options.errorCallback(filledErrorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillErrorMessage(errorMessage) {
|
||||||
|
var units = self.options.imageTexts.sizeUnits.split(',');
|
||||||
|
return errorMessage
|
||||||
|
.replace('#image_name#', file.name)
|
||||||
|
.replace('#image_size#', humanFileSize(file.size, units))
|
||||||
|
.replace('#image_max_size#', humanFileSize(self.options.imageMaxSize, units));
|
||||||
|
}
|
||||||
|
|
||||||
|
imageUploadFunction(file, onSuccess, onError);
|
||||||
|
};
|
||||||
|
|
||||||
EasyMDE.prototype.createSideBySide = function () {
|
EasyMDE.prototype.createSideBySide = function () {
|
||||||
var cm = this.codemirror;
|
var cm = this.codemirror;
|
||||||
var wrapper = cm.getWrapperElement();
|
var wrapper = cm.getWrapperElement();
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
// Create new instance
|
// Create new instance
|
||||||
|
import EasyMDE = require('./easymde');
|
||||||
|
|
||||||
const editor = new EasyMDE({
|
const editor = new EasyMDE({
|
||||||
autoDownloadFontAwesome: false,
|
autoDownloadFontAwesome: false,
|
||||||
element: document.getElementById('mdEditor')!,
|
element: document.getElementById('mdEditor')!,
|
||||||
@ -40,7 +42,7 @@ const editor2 = new EasyMDE({
|
|||||||
title: 'Bold',
|
title: 'Bold',
|
||||||
}, '|', { // Separator
|
}, '|', { // Separator
|
||||||
name: 'alert',
|
name: 'alert',
|
||||||
action: (editor) => {
|
action: (editor: EasyMDE) => {
|
||||||
alert('This is from a custom button action!');
|
alert('This is from a custom button action!');
|
||||||
// Custom functions have access to the `editor` instance.
|
// Custom functions have access to the `editor` instance.
|
||||||
},
|
},
|
||||||
@ -84,3 +86,32 @@ const editorImages = new EasyMDE({
|
|||||||
console.error(errorMessage);
|
console.error(errorMessage);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const editorImagesCustom = new EasyMDE({
|
||||||
|
uploadImage: true,
|
||||||
|
imageAccept: 'image/png, image/bmp',
|
||||||
|
imageCSRFToken: undefined,
|
||||||
|
imageMaxSize: 10485760,
|
||||||
|
imageUploadFunction: (file: File, onSuccess, onError) => {
|
||||||
|
console.log(file);
|
||||||
|
onSuccess('http://image.url/9.png');
|
||||||
|
onError('Failed because reasons.');
|
||||||
|
},
|
||||||
|
imageTexts: {
|
||||||
|
sbInit: 'Drag & drop images!',
|
||||||
|
sbOnDragEnter: 'Let it go, let it go',
|
||||||
|
sbOnDrop: 'Uploading...',
|
||||||
|
sbProgress: 'Uploading... (#progress#)',
|
||||||
|
sbOnUploaded: 'Upload complete!',
|
||||||
|
sizeUnits: 'b,Kb,Mb'
|
||||||
|
},
|
||||||
|
errorMessages: {
|
||||||
|
noFileGiven: 'Please select a file',
|
||||||
|
typeNotAllowed: 'This file type is not allowed!',
|
||||||
|
fileTooLarge: 'Image too big',
|
||||||
|
importError: 'Something went oops!',
|
||||||
|
},
|
||||||
|
errorCallback: (errorMessage) => {
|
||||||
|
console.error(errorMessage);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
1
types/easymde.d.ts
vendored
1
types/easymde.d.ts
vendored
@ -134,6 +134,7 @@ declare namespace EasyMDE {
|
|||||||
uploadImage?: boolean;
|
uploadImage?: boolean;
|
||||||
imageMaxSize?: number;
|
imageMaxSize?: number;
|
||||||
imageAccept?: string;
|
imageAccept?: string;
|
||||||
|
imageUploadFunction?: (file: File, onSuccess: (url: string) => void, onError: (error: string) => void) => void;
|
||||||
imageUploadEndpoint?: string;
|
imageUploadEndpoint?: string;
|
||||||
imageCSRFToken?: string;
|
imageCSRFToken?: string;
|
||||||
imageTexts?: ImageTextsOptions;
|
imageTexts?: ImageTextsOptions;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user