Search code examples
javascriptajaxformsflasktinymce

How to submit form with image uploads only if promise was not rejected in TinyMCE


I am making a form where the user uploads local files onto the TinyMCE editor to which upon form submission they will be sent to the Flask server to store the image files. I have automatic_uploads set to false for this and I'm also using a custom image_upload_handler.

My problem is that if one of the images is too big, say it exceeds 1MB, then I want to reject that and not submit the form (but also not reset everything the user has already written).

Handler and init functions

// Taken from the TinyMCE v6 docs example, but I added image size checking.
const example_image_upload_handler = (blobInfo, progress) => new Promise((resolve, reject) => {

    // Reject any images uploaded that are too big.
    var image_size = blobInfo.blob().size;  // size in bytes
    var image_name = blobInfo.blob().filename;
    var max_size   = 1048576
    if( image_size  > max_size ){
        reject("File too large! Max 1MB");
        return;  // Why isn't this the end of it?
    }

    const xhr = new XMLHttpRequest();
    xhr.withCredentials = false;
    xhr.open('POST', '/upload_image');

    xhr.upload.onprogress = (e) => {
    progress(e.loaded / e.total * 100);
    };

    xhr.onload = () => {
    if (xhr.status === 403) {
        reject({ message: 'HTTP Error: ' + xhr.status, remove: true });
        return;
    }

    if (xhr.status < 200 || xhr.status >= 300) {
        reject('HTTP Error: ' + xhr.status);
        return;
    }

    const json = JSON.parse(xhr.responseText);

    if (!JSON || typeof json.location != 'string') {
        reject('Invalid JSON: ' + xhr.responseText);
        return;
    }

    resolve(json.location);
    };

    xhr.onerror = () => {
    reject('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
    };

    const formData = new FormData();
    formData.append('file', blobInfo.blob(), blobInfo.filename());
    xhr.send(formData);
    });

tinymce.init({
    selector: '#content',
    height: 500,
    plugins: 'advlist auto-link lists link image charmap preview anchor page break wordcount',
    toolbar_mode: 'floating',
    automatic_uploads: false,
    images_upload_handler: example_image_upload_handler,
    });

Using uploadImages() to submit a form

document.addEventListener("DOMContentLoaded", function() {
    const postSubmitButton = document.querySelector(".submit-post");

    // Called when form button is submitted.
    postSubmitButton.addEventListener("click", function() {
        tinymce.activeEditor.uploadImages()
        .then(() => {
            document.forms[0].submit();  // I want to submit this only if the
        });                              // Promise is not rejected.
    });
});

If a normal-sized image is posted it submits fine and the image is correctly uploaded to the server.

If, however, a larger-sized image is posted the form is still submitted even when the Promise gets rejected and returned. Then the image is stored as base64. I have no idea how to stop that.

I am entirely new to how Promises work and relatively new to Javascript so any help on this would be greatly appreciated.


Solution

  • Solved, but in a tacky way.

    I used a global boolean variable to track whether the file size is okay or not as a condition to submit the form.