mirror of
https://github.com/Ionaru/easy-markdown-editor
synced 2025-07-16 06:24:28 -06:00
[wip upload-image] Better errors support and small code improvements
This commit is contained in:
parent
9f33099b1c
commit
d374c5faec
19
README.md
19
README.md
@ -152,16 +152,19 @@ easyMDE.value('New input for **EasyMDE**');
|
||||
- **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`.
|
||||
- **imageUploadEndpoint**: The endpoint where the images data will be sent, via an asynchronous *POST* request. The server is supposed to save this image, and if it's successful, return a 200-OK HTTP response containing the relative path of the image. No default value.
|
||||
- **imageTexts**: Several string literals used in image-upload features:
|
||||
- **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.`,
|
||||
- **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.`.
|
||||
- **sbOnDragEnter**: Status message displayed when the user drags a file to the text area. Defaults to `Drop image to upload it.`.
|
||||
- **sbOnDrop**: Status message displayed when the user drops a file in the text area. Defaults to `Uploading images #images_names#`.
|
||||
- **sbProgress**: Status message displayed to show uploading progress. Defaults to `Uploading #file_name#: #progress#%`,
|
||||
- **sbOnUploaded**: Status message displayed when the image has been uploaded. Defaults to `Uploaded #image_name#`,
|
||||
- **errorImport**: Error message prompted when the served did not return a 200 response code. Defaults to `Can not import #image_name#`,
|
||||
- **errorImageTooBig**: Error message prompted to the user when the size of the image being imported is bigger than the `imageMaxSize`, where `#image_name#`, `#image_size#` and `#image_max_size#` will replaced by their respective values. Defaults to `Image #image_name# is too big (#image_size#).\n' +
|
||||
'Maximum file size is #image_max_size#.`.
|
||||
- **sbProgress**: Status message displayed to show uploading progress. Defaults to `Uploading #file_name#: #progress#%`.
|
||||
- **sbOnUploaded**: Status message displayed when the image has been uploaded. Defaults to `Uploaded #image_name#`.
|
||||
- **sizeUnits**: A comma-separated list of units used to display messages with human-readable file sizes. Defaults to `b,Kb,Mb`.
|
||||
- **errorMessages**: Errors displayed to the user, mainly on alert popups, where `#image_name#`, `#image_size#` and `#image_max_size#` will replaced by their respective values, that can be used for customization or internationalization:
|
||||
- **noFileGiven**: The server did not receive any file from the user. Defaults to `You must select a file.`.
|
||||
- **imageTypeNotAllowed**: The user send a file type which doesn't match the `imageAccept` list, or the server returned this error code. Defaults to `This image type is not allowed.`.
|
||||
- **imageTooLarge**: The size of the image being imported is bigger than the `imageMaxSize`, or if the server returned this error code. Defaults to `Image #image_name# is too big (#image_size#).\nMaximum file size is #image_max_size#.`.
|
||||
- **imageImportError**: An unexpected error occurred when uploading the image. Defaults to `Something went wrong when uploading the image #image_name#.`.
|
||||
|
||||
- **renderingConfig**: Adjust settings for parsing the Markdown during previewing (not editing).
|
||||
- **codeSyntaxHighlighting**: If set to `true`, will highlight using [highlight.js](https://github.com/isagalaev/highlight.js). Defaults to `false`. To use this feature you must include highlight.js on your page or pass in using the `hljs` option. For example, include the script and the CSS files like:<br>`<script src="https://cdn.jsdelivr.net/highlight.js/latest/highlight.min.js"></script>`<br>`<link rel="stylesheet" href="https://cdn.jsdelivr.net/highlight.js/latest/styles/github.min.css">`
|
||||
- **hljs**: An injectible instance of [highlight.js](https://github.com/isagalaev/highlight.js). If you don't want to rely on the global namespace (`window.hljs`), you can provide an instance here. Defaults to `undefined`.
|
||||
|
@ -705,6 +705,7 @@ function drawImage(editor) {
|
||||
|
||||
/**
|
||||
* Action for opening the browse-file window to upload an image to a server.
|
||||
* @param editor {EasyMDE} The EasyMDE object
|
||||
*/
|
||||
function drawUploadedImage(editor) {
|
||||
// TODO: Draw the image template with a fake url, ie: ''
|
||||
@ -714,7 +715,7 @@ function drawUploadedImage(editor) {
|
||||
|
||||
/**
|
||||
* Action executed after an image have been successfully imported on the server.
|
||||
* @param editor The EasyMDE object
|
||||
* @param editor {EasyMDE} The EasyMDE object
|
||||
* @param url {string} The url of the uploaded image
|
||||
*/
|
||||
function afterImageUploaded(editor, url) {
|
||||
@ -1411,18 +1412,31 @@ var blockStyles = {
|
||||
'italic': '*',
|
||||
};
|
||||
|
||||
/**
|
||||
* Texts displayed to the user (mainly on the status bar) for the import image
|
||||
* feature. Can be used for customization or internationalization.
|
||||
*/
|
||||
var imageTexts = {
|
||||
sbInit: 'Attach files by drag and dropping or pasting from clipboard.',
|
||||
sbOnDragEnter: 'Drop image to upload it.',
|
||||
sbOnDrop: 'Uploading image #images_names#...',
|
||||
sbProgress: 'Uploading #file_name#: #progress#%',
|
||||
sbOnUploaded: 'Uploaded #image_name#',
|
||||
errorImport: 'Can not import #image_name#',
|
||||
errorImageTooBig: 'Image #image_name# is too big (#image_size#).\n' +
|
||||
'Maximum file size is #image_max_size#.',
|
||||
sizeUnits: 'b,Kb,Mb',
|
||||
};
|
||||
|
||||
/**
|
||||
* Errors displayed to the user, mainly on alert popups. Can be used for
|
||||
* customization or internationalization.
|
||||
*/
|
||||
var errorMessages = {
|
||||
noFileGiven: 'You must select a file.',
|
||||
imageTypeNotAllowed: 'This image type is not allowed.',
|
||||
imageTooLarge: 'Image #image_name# is too big (#image_size#).\n' +
|
||||
'Maximum file size is #image_max_size#.',
|
||||
imageImportError: 'Something went wrong when uploading the image #image_name#.',
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface of EasyMDE.
|
||||
*/
|
||||
@ -1534,11 +1548,12 @@ function EasyMDE(options) {
|
||||
options.minHeight = options.minHeight || '300px';
|
||||
|
||||
|
||||
// import-image default configuration
|
||||
// Import-image default configuration
|
||||
options.uploadImage = options.uploadImage || false;
|
||||
options.imageMaxSize = options.imageMaxSize || 1024*1024*2;
|
||||
options.imageTexts = extend({}, imageTexts, options.imageTexts || {});
|
||||
options.imageAccept = options.imageAccept || 'image/png, image/jpeg';
|
||||
options.imageTexts = extend({}, imageTexts, options.imageTexts || {});
|
||||
options.errorMessages = extend({}, errorMessages, options.errorMessages || {});
|
||||
|
||||
|
||||
// Change unique_id to uniqueId for backwards compatibility
|
||||
@ -1605,18 +1620,17 @@ EasyMDE.prototype.uploadImages = function(files) {
|
||||
|
||||
this.uploadImage(files[i], function onSuccess(imageUrl) {
|
||||
afterImageUploaded(self, imageUrl);
|
||||
}, function onFailure(imageName, errorStatus, errorStatusText) {
|
||||
alert(self.options.imageTexts.errorImport.replace('#image_name#', imageName));
|
||||
console.log('EasyMDE: error ' + errorStatus + ' when importing image ' + imageName + ': ' + errorStatusText);
|
||||
}, function onFailure(error) {
|
||||
alert(error);
|
||||
});
|
||||
}
|
||||
this.updateStatusBar('upload-image', self.options.imageTexts.sbOnDrop.replace('#images_names#', names.join(', ')));
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param itemName
|
||||
* @param content
|
||||
* Update an item in the status bar.
|
||||
* @param itemName {string} The name of the item to update (ie. 'upload-image', 'autosave', etc.).
|
||||
* @param content {string} the new content of the item to write in the status bar.
|
||||
*/
|
||||
EasyMDE.prototype.updateStatusBar = function(itemName, content) {
|
||||
var matchingClasses = this.gui.statusbar.getElementsByClassName(itemName);
|
||||
@ -1890,23 +1904,23 @@ EasyMDE.prototype.clearAutosavedValue = function () {
|
||||
/**
|
||||
* Upload an image to the server.
|
||||
*
|
||||
* @param file {File} The image to upload as a HTML5 File object (https://developer.mozilla.org/en-US/docs/Web/API/File)
|
||||
* @param onSuccess {function} A callback function to execute after the image have been successfully uploaded, with parameters:
|
||||
* @param file {File} The image to upload, as a HTML5 File object (https://developer.mozilla.org/en-US/docs/Web/API/File)
|
||||
* @param onSuccess {function} A callback function to execute after the image has been successfully uploaded, with one parameter:
|
||||
* - url (string): The URL of the uploaded image.
|
||||
* @param onError {function} A callback function to execute when the image upload fails, with parameters:
|
||||
* - fileName: the name of the image file provided by the user.
|
||||
* - errorStatus (number): The status of the response of the request, provided by XMLHttpRequest (see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/status).
|
||||
* - errorStatusText (string): the response string returned by the HTTP server, provided by XMLHttpRequest (see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/statusText).
|
||||
* @param onError {function} A callback function to execute when the image upload fails, with one parameter:
|
||||
* - error (string): the detailed error to display to the user (based on messages from options.errorMessages).
|
||||
*/
|
||||
EasyMDE.prototype.uploadImage = function(file, onSuccess, onError) {
|
||||
if (file.size >= this.options.imageMaxSize) {
|
||||
var units = this.options.imageTexts.sizeUnits.split(',');
|
||||
alert(this.options.imageTexts.errorImageTooBig
|
||||
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(this.options.imageMaxSize, units))
|
||||
);
|
||||
return;
|
||||
.replace('#image_max_size#', humanFileSize(self.options.imageMaxSize, units));
|
||||
}
|
||||
|
||||
if (file.size > this.options.imageMaxSize) {
|
||||
onError(fillErrorMessage(this.options.errorMessages.imageTooLarge));
|
||||
}
|
||||
|
||||
var formData = new FormData();
|
||||
@ -1914,23 +1928,41 @@ EasyMDE.prototype.uploadImage = function(file, onSuccess, onError) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('POST', this.options.imageUploadEndpoint);
|
||||
request.send(formData);
|
||||
|
||||
var self = this;
|
||||
|
||||
request.onprogress = function (event) {
|
||||
if (event.lengthComputable) {
|
||||
// TODO: test with a big image on a remote web server
|
||||
// FIXME: progress doesn't work well
|
||||
var progress = '' + Math.round((event.loaded * 100) / event.total);
|
||||
self.updateStatusBar('upload-image', self.options.imageTexts.sbProgress.replace('#file_name#', file.name).replace('#progress#', progress));
|
||||
}
|
||||
};
|
||||
|
||||
request.onload = function () {
|
||||
if(this.status === 200) {
|
||||
try {
|
||||
var response = JSON.parse(this.responseText);
|
||||
} catch (error) {
|
||||
console.log('EasyMDE: The server did not return a valid json.');
|
||||
onError(fillErrorMessage(self.options.errorMessages.imageImportError));
|
||||
return;
|
||||
}
|
||||
if(this.status === 200 && response && response.data && !response.error) {
|
||||
onSuccess(window.location.origin + '/' + this.responseText);
|
||||
} else {
|
||||
onError(file.name, this.status, this.statusText.toString());
|
||||
// TODO: handle several errors defined by the server (bad type, file too large, etc.)
|
||||
if(response.error && response.error in self.options.errorMessages) {
|
||||
onError(fillErrorMessage(self.options.errorMessages[response.error]));
|
||||
} else {
|
||||
console.log('EasyMDE: Received an unexpected response after uploading the image.'
|
||||
+ this.status + ' (' + this.statusText + ')');
|
||||
onError(fillErrorMessage(self.options.errorMessages.imageImportError));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = function (event) {
|
||||
console.log('EasyMDE: An unexpected error occurred when trying to upload the image.'
|
||||
+ event.target.status + ' (' + event.target.statusText + ')');
|
||||
onError(self.options.errorMessages.imageImportError);
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user