Code Monkey home page Code Monkey logo

Comments (20)

anthonyjb avatar anthonyjb commented on August 18, 2024

Hi @jlgit, thanks for the kind words. Once inserted the image should be resizeable and dragable, so sounds like there's an error. Any chance you can post any error output in the console along with your image uploaded code?

from contenttools.

jlgit avatar jlgit commented on August 18, 2024

I was able to figurate out, there was a mix of browser cache and old css acting out, thank you very much for your response, I really appreciate what you've done with this code!

from contenttools.

JapSeyz avatar JapSeyz commented on August 18, 2024

@jlgit could you help me?

The image setup is not working for me, no matter what I do, and the documentation for Cloudinary is super buggy

from contenttools.

anthonyjb avatar anthonyjb commented on August 18, 2024

Hey @Sirlazer2 if you post me your code I'll take a look for you?

from contenttools.

JapSeyz avatar JapSeyz commented on August 18, 2024

I don't have anything yet, I've tired both local and cloudinary so far, but ended up deleting it multiple times.

But here is the documentation flaws I've found so far

// The "=" is some leftover thing from Coffeescript I suppose
"function = cloudinaryImageUploader(dialog) {"

//Object is not defined
for (name in transform) {
if (object.hasOwnProperty(name)) {
transformArgs.push(name + '_' + object[name]);
}
}

//A disturbing lack of curly brackets around the array.
"transforms.push(c: 'fill', w: element.size()[0], h: element.size()[1]);"

From URL: http://getcontenttools.com/tutorials/image-uploads-with-cloudinary

from contenttools.

anthonyjb avatar anthonyjb commented on August 18, 2024

Thanks for highlighting those issue - yes some of them certainly look left over from CoffeeScript. If you give me an hour I'll run through the tutorial now and clean those up an post a full working JavaScript example for you?

from contenttools.

JapSeyz avatar JapSeyz commented on August 18, 2024

That would be absolutely fantastic!

Thank you so much :)

from contenttools.

anthonyjb avatar anthonyjb commented on August 18, 2024

@Sirlazer2 Make that +15 minutes - almost there just an issue with the resize code in the page now.

from contenttools.

JapSeyz avatar JapSeyz commented on August 18, 2024

No worries

from contenttools.

anthonyjb avatar anthonyjb commented on August 18, 2024

Right (eventually) - I think that's the tutorial correctly updated and as promised a full working example. Let me know how you get on.

// Define settings for the uploader
var CLOUDINARY_PRESET_NAME = 'ctpreset';
var CLOUDINARY_RETRIEVE_URL = 'http://res.cloudinary.com/contenttools/image/upload';
var CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/contenttools/image/upload';

// Define the image uploader
function cloudinaryImageUploader(dialog) {
     var image, xhr, xhrComplete, xhrProgress;

    // Set up the event handlers
    dialog.bind('imageUploader.cancelUpload', function () {
        // Cancel the current upload

        // Stop the upload
        if (xhr) {
            xhr.upload.removeEventListener('progress', xhrProgress);
            xhr.removeEventListener('readystatechange', xhrComplete);
            xhr.abort();
        }

        // Set the dialog to empty
        dialog.state('empty');
    });

    dialog.bind('imageUploader.clear', function () {
        // Clear the current image
        dialog.clear();
        image = null;
    });

    dialog.bind('imageUploader.fileReady', function (file) {
        // Upload a file to Cloudinary
        var formData;

        // Define functions to handle upload progress and completion
        function xhrProgress(ev) {
            // Set the progress for the upload
            dialog.progress((ev.loaded / ev.total) * 100);
        }

        function xhrComplete(ev) {
            var response;

            // Check the request is complete
            if (ev.target.readyState != 4) {
                return;
            }

            // Clear the request
            xhr = null
            xhrProgress = null
            xhrComplete = null

            // Handle the result of the upload
            if (parseInt(ev.target.status) == 200) {
                // Unpack the response (from JSON)
                response = JSON.parse(ev.target.responseText);

                // Store the image details
                image = {
                    angle: 0,
                    height: parseInt(response.height),
                    maxWidth: parseInt(response.width),
                    width: parseInt(response.width)
                    };

                // Apply a draft size to the image for editing
                image.filename = parseCloudinaryURL(response.url)[0];
                image.url = buildCloudinaryURL(
                    image.filename,
                    [{c: 'fit', h: 600, w: 600}]
                    );

                // Populate the dialog
                dialog.populate(image.url, [image.width, image.height]);

            } else {
                // The request failed, notify the user
                new ContentTools.FlashUI('no');
            }
        }

        // Set the dialog state to uploading and reset the progress bar to 0
        dialog.state('uploading');
        dialog.progress(0);

        // Build the form data to post to the server
        formData = new FormData();
        formData.append('file', file);
        formData.append('upload_preset', CLOUDINARY_PRESET_NAME);

        // Make the request
        xhr = new XMLHttpRequest();
        xhr.upload.addEventListener('progress', xhrProgress);
        xhr.addEventListener('readystatechange', xhrComplete);
        xhr.open('POST', CLOUDINARY_UPLOAD_URL, true);
        xhr.send(formData);
    });

    function rotate(angle) {
        // Handle a request by the user to rotate the image
        var height, transforms, width;

        // Update the angle of the image
        image.angle += angle;

        // Stay within 0-360 degree range
        if (image.angle < 0) {
            image.angle += 360;
        } else if (image.angle > 270) {
            image.angle -= 360;
        }

        // Rotate the image's dimensions
        width = image.width;
        height = image.height;
        image.width = height;
        image.height = width;
        image.maxWidth = width;

        // Build the transform to rotate the image
        transforms = [{c: 'fit', h: 600, w: 600}];
        if (image.angle > 0) {
            transforms.unshift({a: image.angle});
        }

        // Build a URL for the transformed image
        image.url = buildCloudinaryURL(image.filename, transforms);

        // Update the image in the dialog
        dialog.populate(image.url, [image.width, image.height]);
    }

    dialog.bind('imageUploader.rotateCCW', function () { rotate(-90); });
    dialog.bind('imageUploader.rotateCW', function () { rotate(90); });

    dialog.bind('imageUploader.save', function () {
        // Handle a user saving an image
        var cropRegion, cropTransform, imageAttrs, ratio, transforms;

        // Build a list of transforms
        transforms = [];

        // Angle
        if (image.angle != 0) {
            transforms.push({a: image.angle});
        }

        // Crop
        cropRegion = dialog.cropRegion();
        if (cropRegion.toString() != [0, 0, 1, 1].toString()) {
            cropTransform = {
                c: 'crop',
                x: parseInt(image.width * cropRegion[1]),
                y: parseInt(image.height * cropRegion[0]),
                w: parseInt(image.width * (cropRegion[3] - cropRegion[1])),
                h: parseInt(image.height * (cropRegion[2] - cropRegion[0]))
                };
            transforms.push(cropTransform);

            // Update the image size based on the crop
            image.width = cropTransform.w;
            image.height = cropTransform.h;
            image.maxWidth = cropTransform.w;
        }

        // Resize (the image is inserted in the page at a default size)
        if (image.width > 400 || image.height > 400) {
            transforms.push({c: 'fit', w: 400, h: 400});

            // Update the size of the image in-line with the resize
            ratio = Math.min(400 / image.width, 400 / image.height);
            image.width *= ratio;
            image.height *= ratio;
        }

        // Build a URL for the image we'll insert
        image.url = buildCloudinaryURL(image.filename, transforms);

        // Build attributes for the image
        imageAttrs = {'alt': '', 'data-ce-max-width': image.maxWidth};

        // Save/insert the image
        dialog.save(image.url, [image.width, image.height]);
    });
}

function buildCloudinaryURL(filename, transforms) {
    // Build a Cloudinary URL from a filename and the list of transforms
    // supplied. Transforms should be specified as objects (e.g {a: 90} becomes
    // 'a_90').
    var i, name, transform, transformArgs, transformPaths, urlParts;

    // Convert the transforms to paths
    transformPaths = [];
    for  (i = 0; i < transforms.length; i++) {
        transform = transforms[i];

        // Convert each of the object properties to a transform argument
        transformArgs = [];
        for (name in transform) {
            if (transform.hasOwnProperty(name)) {
                transformArgs.push(name + '_' + transform[name]);
            }
        }

        transformPaths.push(transformArgs.join(','));
    }

    // Build the URL
    urlParts = [CLOUDINARY_RETRIEVE_URL];
    if (transformPaths.length > 0) {
        urlParts.push(transformPaths.join('/'));
    }
    urlParts.push(filename);

    return urlParts.join('/');
}

function parseCloudinaryURL(url) {
    // Parse a Cloudinary URL and return the filename and list of transforms
    var filename, i, j, transform, transformArgs, transforms, urlParts;

    // Strip the URL down to just the transforms, version (optional) and
    // filename.
    url = url.replace(CLOUDINARY_RETRIEVE_URL, '');

    // Split the remaining path into parts
    urlParts = url.split('/');

    // The path starts with a '/' so the first part will be empty and can be
    // discarded.
    urlParts.shift();

    // Extract the filename
    filename = urlParts.pop();

    // Strip any version number from the URL
    if (urlParts.length > 0 && urlParts[urlParts.length - 1].match(/v\d+/)) {
        urlParts.pop();
    }

    // Convert the remaining parts into transforms (e.g `w_90,h_90,c_fit >
    // {w: 90, h: 90, c: 'fit'}`).
    transforms = [];
    for (i = 0; i < urlParts.length; i++) {
        transformArgs = urlParts[i].split(',');
        transform = {};
        for (j = 0; j < transformArgs.length; j++) {
            transform[transformArgs[j].split('_')[0]] =
                transformArgs[j].split('_')[1];
        }
        transforms.push(transform);
    }

    return [filename, transforms];
}

// Capture image resize events and update the Cloudinary URL
ContentEdit.Root.get().bind('taint', function (element) {
    var args, filename, newSize, transforms, url;

    // Check the element tainted is an image
    if (element.constructor.name != 'Image') {
        return;
    }

    // Parse the existing URL
    args = parseCloudinaryURL(element.attr('src'));
    filename = args[0];
    transforms = args[1];

    // If no filename is found then exit (not a Cloudinary image)
    if (!filename) {
        return;
    }

    // Remove any existing resize transform
    if (transforms.length > 0 &&
            transforms[transforms.length -1]['c'] == 'fill') {
        transforms.pop();
    }

    // Change the resize transform for the element
    transforms.push({c: 'fill', w: element.size()[0], h: element.size()[1]});
    url = buildCloudinaryURL(filename, transforms);
    if (url != element.attr('src')) {
        element.attr('src', url);
    }
});

window.onload = function() {
    var editor, req;

    ContentTools.IMAGE_UPLOADER = cloudinaryImageUploader;

    editor = ContentTools.EditorApp.get();
    editor.init('.editable', 'data-name');
};

Don't forget to update your cloud name and upload preset in the settings.

from contenttools.

anthonyjb avatar anthonyjb commented on August 18, 2024

P.S @Sirlazer2 - thank you for highlighting this and I'm sorry about this - those were some really sloppy examples on my behalf.

from contenttools.

JapSeyz avatar JapSeyz commented on August 18, 2024

@anthonyjb Hah, it happens.

I am still not having any luck though. I have two files, editor.js with auto-saving feature, and image.js with the code you just provided, just copied and pasted.

I am not even getting a progress bar, but no server error either.

from contenttools.

jlgit avatar jlgit commented on August 18, 2024

Hello Guys;
I'm sorry I didn't see the request from @Siriazer2 before, it's being a crazy day today, please let me know if you need any help still.

To @anthonyjb, thank you very much for the code, I think this make it easier to handle!

from contenttools.

anthonyjb avatar anthonyjb commented on August 18, 2024

@Sirlazer2 ok I've updated my code above to include a really simple editor initialization as well - you should be able to drop it in to the editor.js file for now and remove image.js for the moment - just to see if that works. It's working for me in the sandbox demo in the repo at least.

from contenttools.

anthonyjb avatar anthonyjb commented on August 18, 2024

@jlgit thanks 👍

from contenttools.

jlgit avatar jlgit commented on August 18, 2024

ok @Sirlazer2, Search for the function imageUploader.fileReady and replace it with this code.

dialog.bind('imageUploader.fileReady', function (file) {
    var formData;
    uploadProgress = function (ev) {
        // Set the progress for the upload
        dialog.progress((ev.loaded / ev.total) * 100);
    }
    uploadComplete = function (ev) {
        xhr = null
        uploadProgress = null
        uploadComplete = null

        if (parseInt(ev.target.status) == 200) {
            var response = JSON.parse(ev.target.responseText);
            image = {
                size: response.size,
                url: response.url
            };
            dialog.populate(image.url, image.size);
        } else {
            // The request failed, notify the user
            new ContentTools.FlashUI('no');
        }
    }

    dialog.state('uploading');
    dialog.progress(0);

    // POST variables to send to the server
    formData = new FormData()
    formData.append('folder_name', 'uploads');
    formData.append('image', file);

    xhr = new XMLHttpRequest();
    xhr.upload.addEventListener('progress', uploadProgress);
    xhr.addEventListener('load', uploadComplete);
    xhr.open('POST', '_UPLOAD_HANDLER_SERVER_SIDE', true);
    xhr.send(formData);
});

The server side should handle the image resize and response with a json object with the following info:

{"url":"\/uploads\/9375035le.jpg","size":[500,362]}

Try that and let us know.

from contenttools.

JapSeyz avatar JapSeyz commented on August 18, 2024

@anthonyjb It's working now.

I suggest uploading a full example somewhere, it's always nicer to look at completed code than something that's patched together through a tutorial. Especially since you somewhere note "This belongs under function x" or "We can put this at the bottom of x, for now".

Also, thank you so much for the supreme and extremely fast support. I am super impressed with you and ContentTools! 👍

from contenttools.

anthonyjb avatar anthonyjb commented on August 18, 2024

@Sirlazer2 great news glad it's working and thanks for sticking with it - I'll be taking your advice re. the full example.

from contenttools.

JapSeyz avatar JapSeyz commented on August 18, 2024

@anthonyjb Of course I'm sticking with it, it does have some great potential, ease of use and is super lightweight - I won't let a mere bug stand in the way of that :p

from contenttools.

ahmedmontacir avatar ahmedmontacir commented on August 18, 2024

hello everyone,
i chose to follow cloudinary code to be able to upload images, seems everything worked well but i did not know how to coordinate between my cloud account and my code even if defined settings:
var CLOUDINARY_PRESET_NAME = 'ctpreset';
var CLOUDINARY_RETRIEVE_URL = 'http://res.cloudinary.com/../image/upload';
var CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/.../image/upload';

if someone could upload succefully and help would be great. thanks

from contenttools.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.