CROP news file upload

Have a question or a suggestion about a 3rd party addon module or plugin?
Let us know here.
Locked
pWorker
Forum Members
Forum Members
Posts: 48
Joined: Wed Aug 31, 2016 1:30 pm

CROP news file upload

Post by pWorker »

Hi all,

is there an efficient way to implement jCrop to the editarticle section of the news module (also for Frontend)?

I want to jCrop if a selection of an image has be done and the result shall be stored as field->value to the db.

Or are there other ways to implement custom cropping?

Main Problem is, that i can`t get the tmp- image- selection as callable output before "I" press submit.

PS: I know CGSmartImage, but i need custom cropping on the fly.

Regards
User avatar
velden
Dev Team Member
Dev Team Member
Posts: 3313
Joined: Mon Nov 28, 2011 9:29 am
Location: The Netherlands

Re: CROP news file upload

Post by velden »

You might need to read this https://docs.cmsmadesimple.org/customiz ... -templates

If it's only JS I think it should be possible.
pWorker
Forum Members
Forum Members
Posts: 48
Joined: Wed Aug 31, 2016 1:30 pm

Re: CROP news file upload

Post by pWorker »

Hi velden,

thanks for your answer. I have to say, sometimes i`m really disappointed of the cmsms functionality. The custom cropping of an image shouldn`t be an issue in 2016, think of all social media platforms where it is set as standard...

All plugins i saw, only support postprocessing of uploaded files, so after a while ifound Jcrop and simplecropper. I added the (js) script files and css to my editarticle.tpl under module_custom.

Now im at the point, that i can do a clientside crop which delivers the result as a base64 encoded image in a specific div box.

My actual problem is, that i cant set that result as an input value for the custom field input type = "file".

I have somehow, as far as i could understand, create a blob file out of the dataread img which should be sent to the server as the value for my input field. So, here it ends with pure js.

Another idea was to save the source as a text string (in an textarea input field) and to work with that.

My question to you: what are there for possibilities to create the value for the custom field value attribute? May I also use a php function or ajax to store my cropping result as the {$field->value}to the db? And would i have to insert that function in an udt?

mfg

Code: Select all


----------------------------------------------

Cms Version: 2.1.4

Installed Modules:

    AdminSearch: 1.0.1
    CGExtensions: 1.53.13
    CGSimpleSmarty: 2.1.4
    CGUserDirectory: 1.5
    CMSContentManager: 1.1
    CMSMailer: 6.2.14
    CustomContent: 1.10
    DesignManager: 1.1.1
    FileManager: 1.5.2
    FormBuilder: 0.8.1.4
    FrontEndUsers: 2.1.1
    Gallery: 2.1.6
    MicroTiny: 2.0.3
    ModuleManager: 2.0.2
    MultiDomains: 2.2.3
    Navigator: 1.0.3
    News: 2.50.5
    Search: 1.50.2
    SelfRegistration: 1.9.7


Config Information:

    php_memory_limit:
    max_upload_size: 256000000
    url_rewriting: mod_rewrite
    page_extension:
    query_var: page
    auto_alias_content: true
    locale:
    set_names: true
    timezone: Europe/Berlin
    permissive_smarty: false


Php Information:

    phpversion: 7.0.11
    md5_function: An (Ja)
    json_function: An (Ja)
    gd_version: 2
    tempnam_function: An (Ja)
    magic_quotes_runtime: Aus (Nein)
    E_ALL: 22527
    E_STRICT: 0
    E_DEPRECATED: 0
    test_file_timedifference: No time difference found
    test_db_timedifference: No time difference found
    create_dir_and_file: 1
    memory_limit: 128M
    max_execution_time: 192
    register_globals: Aus (Nein)
    output_buffering: 4096
    disable_functions: exec, system, shell_exec, popen, pclose, proc_open, proc_close, proc_get_status, proc_nice, proc_terminate, show_source, escapeshellcmd, escapeshellarg
    open_basedir: /home/xxx/logdateien/stats
    test_remote_url: Erfolgreich abgeschlossen
    file_uploads: An (Ja)
    post_max_size: 260M
    upload_max_filesize: 256M
    session_save_path: Keine Prüfung, da eine „open basedir“-Beschränkung aktiviert ist
    session_use_cookies: An (Ja)
    xml_function: An (Ja)
    xmlreader_class: An (Ja)
    check_ini_set: An (Ja)
    curl: An


Performance Information:

    allow_browser_cache: Aus (Nein)
    browser_cache_expiry: 60
    php_opcache: Aus (Nein)
    smarty_cache: Aus (Nein)
    smarty_compilecheck: Aus (Nein)
    smarty_cache_udt: Aus (Nein)
    auto_clear_cache_age: An (Ja)

Server Information:

    Server Software: Apache/2.4.10 (Debian)
    Server Api: cgi-fcgi
    Server Os: Linux 3.16.0-4-amd64 An x86_64
    Server Db Type: MySQL (mysqli)
    Server Db Version: 5.5.52
    Server Db Grants: Es konnte keine „GRANT ALL“-Berechtigung gefunden werden. Dies kann bedeuten, dass Sie bei der Installation oder beim Entfernen von Modulen, oder sogar beim Hinzufügen und Löschen von Elementen, einschließlich Seiten, Probleme haben könnten.


Permission Information:

    tmp: /home/xxx/tmp (0775)
    tmp_cache: /home/xxx/tmp/cache (0775)
    templates_c: /home/xxx/tmp/templates_c (0775)
    modules: /home/xxx/modules (0775)
    uploads: /home/xxx/uploads (0775)
    Maske zum Erstellen von Dateien (umask): /home/xxx/tmp/cache (0775)
    config_file: 0444

----------------------------------------------
pWorker
Forum Members
Forum Members
Posts: 48
Joined: Wed Aug 31, 2016 1:30 pm

Re: CROP news file upload

Post by pWorker »

Code (editarticle.tpl):

Code: Select all


<__script__ type="text/javascript">
  
  
   
    $(document).ready(function () {
        $('[name$=apply],[name$=submit]').hide();

        $('#edit_news').dirtyForm({
            onDirty : function () {
                $('[name$=apply],[name$=submit]').show('slow');
            }
        });
        $(document).on('cmsms_textchange', function (event) {
            // editor text change, set the form dirty.
            $('#edit_news').dirtyForm('option', 'dirty', true);
        });
        $(document).on('click', '[name$=submit],[name$=apply],[name$=cancel]', function () {
            $('#edit_news').dirtyForm('option', 'disabled', true);
        });
        $('#fld11').click(function () {
            $('#expiryinfo').toggle('slow');
        });
        $('#{$actionid}cancel').click (function () {
            $(this).closest('form').attr('novalidate', 'novalidate');
        });
			
			$('.cropme').simpleCropper();
 </__script>



...


{elseif $field->type == 'file'}
                
       {if $field->prompt == 'Artikelbild'}               
                        
                 <div class="cropme" style="width: 405px; height: 200px;"></div>      
                  <input type="file" id="{$field->idattr}" name="{$field->nameattr}" />                                        
                                      
                    {if !empty($field->value)} {$delete_field_val} <input type="checkbox" name="{$field->delete}" value="delete" />{/if}

Simplecropper:

Code: Select all

/* 
    Author     : Tomaz Dragar
    Mail       : <tomaz@dragar.net>
    Homepage   : http://www.dragar.net
*/

(function ($) {

    $.fn.simpleCropper = function (onComplete) {

        var image_dimension_x = 600;
        var image_dimension_y = 600;
        var scaled_width = 0;
        var scaled_height = 0;
        var x1 = 0;
        var y1 = 0;
        var x2 = 0;
        var y2 = 0;
        var current_image = null;
        var image_filename = null;
        var aspX = 1;
        var aspY = 1;
        var file_display_area = null;
        var ias = null;
        var original_data = null;
        var jcrop_api;
        var bottom_html = "<input type='file' id='fileInput' name='files[]'/ accept='image/*'><canvas id='myCanvas' style='display:none;'></canvas><div id='modal'></div><div id='preview'><div class='buttons'><div class='cancel'></div><div class='ok'></div></div></div>";
        $('body').append(bottom_html);

        //add click to element
        this.click(function () {
            aspX = $(this).width();
            aspY = $(this).height();
            file_display_area = $(this);
            $('#fileInput').click();
        });

        $(document).ready(function () {
            //capture selected filename
            $('#fileInput').change(function (click) {
                imageUpload($('#preview').get(0));
                // Reset input value
                $(this).val("");
            });

            //ok listener
            $('.ok').click(function () {
                preview();
                $('#preview').delay(100).hide();
                $('#modal').hide();
                jcrop_api.destroy();
                reset();
            });

            //cancel listener
            $('.cancel').click(function (event) {
                $('#preview').delay(100).hide();
                $('#modal').hide();
                jcrop_api.destroy();
                reset();
            });
        });

        function reset() {
            scaled_width = 0;
            scaled_height = 0;
            x1 = 0;
            y1 = 0;
            x2 = 0;
            y2 = 0;
            current_image = null;
            image_filename = null;
            original_data = null;
            aspX = 1;
            aspY = 1;
            file_display_area = null;
        }

        function imageUpload(dropbox) {
            var file = $("#fileInput").get(0).files[0];

            var imageType = /image.*/;

            if (file.type.match(imageType)) {
                var reader = new FileReader();
                image_filename = file.name;

                reader.onload = function (e) {
                    // Clear the current image.
                    $('#photo').remove();

                    original_data = reader.result;

                    // Create a new image with image crop functionality
                    current_image = new Image();
                    current_image.src = reader.result;
                    current_image.id = "photo";
                    current_image.style['maxWidth'] = image_dimension_x + 'px';
                    current_image.style['maxHeight'] = image_dimension_y + 'px';
                    current_image.onload = function () {
                        // Calculate scaled image dimensions
                        if (current_image.width > image_dimension_x || current_image.height > image_dimension_y) {
                            if (current_image.width > current_image.height) {
                                scaled_width = image_dimension_x;
                                scaled_height = image_dimension_x * current_image.height / current_image.width;
                            }
                            if (current_image.width < current_image.height) {
                                scaled_height = image_dimension_y;
                                scaled_width = image_dimension_y * current_image.width / current_image.height;
                            }
                            if (current_image.width == current_image.height) {
                                scaled_width = image_dimension_x;
                                scaled_height = image_dimension_y;
                            }
                        }
                        else {
                            scaled_width = current_image.width;
                            scaled_height = current_image.height;
                        }

                        // set the image size to the scaled proportions which is required for at least IE11
                        current_image.style['width'] = scaled_width + 'px';
                        current_image.style['height'] = scaled_height + 'px';

                        // Position the modal div to the center of the screen
                        $('#modal').css('display', 'block');
                        var window_width = $(window).width() / 2 - scaled_width / 2 + "px";
                        var window_height = $(window).height() / 2 - scaled_height / 2 + "px";

                        // Show image in modal view
                        $("#preview").css("top", window_height);
                        $("#preview").css("left", window_width);
                        $('#preview').show(500);


                        // Calculate selection rect
                        var selection_width = 0;
                        var selection_height = 0;

                        var max_x = Math.floor(scaled_height * aspX / aspY);
                        var max_y = Math.floor(scaled_width * aspY / aspX);


                        if (max_x > scaled_width) {
                            selection_width = scaled_width;
                            selection_height = max_y;
                        }
                        else {
                            selection_width = max_x;
                            selection_height = scaled_height;
                        }

                        ias = $(this).Jcrop({
                            onSelect: showCoords,
                            onChange: showCoords,
                            bgColor: '#747474',
                            bgOpacity: .4,
                            aspectRatio: aspX / aspY,
                            setSelect: [0, 0, selection_width, selection_height]
                        }, function () {
                            jcrop_api = this;
                        });
                    }

                    // Add image to dropbox element
                    dropbox.appendChild(current_image);
                }

                reader.readAsDataURL(file);
            } else {
                dropbox.innerHTML = "File not supported!";
            }
        }

        function showCoords(c) {
            x1 = c.x;
            y1 = c.y;
            x2 = c.x2;
            y2 = c.y2;
        }

        function preview() {
            // Set canvas
            var canvas = document.getElementById('myCanvas');
            var context = canvas.getContext('2d');

            // Delete previous image on canvas
            context.clearRect(0, 0, canvas.width, canvas.height);

            // Set selection width and height
            var sw = x2 - x1;
            var sh = y2 - y1;


            // Set image original width and height
            var imgWidth = current_image.naturalWidth;
            var imgHeight = current_image.naturalHeight;

            // Set selection koeficient
            var kw = imgWidth / $("#preview").width();
            var kh = imgHeight / $("#preview").height();

            // Set canvas width and height and draw selection on it
            canvas.width = aspX;
            canvas.height = aspY;
            context.drawImage(current_image, (x1 * kw), (y1 * kh), (sw * kw), (sh * kh), 0, 0, aspX, aspY);

            // Convert canvas image to normal img
            var dataUrl = canvas.toDataURL();
            var imageFoo = document.createElement('img');
            imageFoo.src = dataUrl;

            // Append it to the body element
            $('#preview').delay(100).hide();
            $('#modal').hide();
            file_display_area.html('');
            file_display_area.append(imageFoo);

            if (onComplete) onComplete(
                {                    
                    "original": { "filename": image_filename, "base64": original_data, "width": current_image.width, "height": current_image.height },
                    "crop": { "x": (x1 * kw), "y": (y1 * kh), "width": (sw * kw), "height": (sh * kh) }
                }
               );
        }

        $(window).resize(function () {
            // Position the modal div to the center of the screen
            var window_width = $(window).width() / 2 - scaled_width / 2 + "px";
            var window_height = $(window).height() / 2 - scaled_height / 2 + "px";

            // Show image in modal view
            $("#preview").css("top", window_height);
            $("#preview").css("left", window_width);
        });
    }
}(jQuery));
User avatar
velden
Dev Team Member
Dev Team Member
Posts: 3313
Joined: Mon Nov 28, 2011 9:29 am
Location: The Netherlands

Re: CROP news file upload

Post by velden »

I don't think I have a complete answer for your question but maybe this helps:

Consider checking the Extensions -> Event Manager and have a look at the NewsArticleAdded and NewsArticleEdited events.

Perhaps it's possible to submit the base64 as a string by a hidden form field and use a UDT (called by those events) to create a file from it. Or if dimensions are ok just use the base64 itself in a data uri
pWorker
Forum Members
Forum Members
Posts: 48
Joined: Wed Aug 31, 2016 1:30 pm

Re: CROP news file upload

Post by pWorker »

Hi velden,

very good hint with the event manager, i didnt even noticed it before ...


Perhaps it's possible to submit the base64 as a string by a hidden form field and use a UDT (called by those events) to create a file from it. Or if dimensions are ok just use the base64 itself in a data uri

That`s exactly the point i do not understand. So, i have this dataurl img, now i have to do at least 3 steps:
  • Make some sort of static image file out of it, so that it can be used later on
  • Write the value for a(!) custom field to show that image (could be simply the embed link to that file)
  • Store that information to the db
If i add a hidden field, how would it be stored as valid entry to the databank under the prompt of the hidden field created?I know, that you can't set the value for the input type ="file" for security reasons.


mfg
User avatar
velden
Dev Team Member
Dev Team Member
Posts: 3313
Joined: Mon Nov 28, 2011 9:29 am
Location: The Netherlands

Re: CROP news file upload

Post by velden »

So, as you can not manipulate the file type field value I'd consider using another input field (hidden, text/text area). I bet jQuery/js can write that base64 string* to it's value 'property' before submission of the form.
*
Now im at the point, that i can do a clientside crop which delivers the result as a base64 encoded image in a specific div box.
Then, after submission, you can do whatever you want with that specific value in your UDT.
calguy1000
Support Guru
Support Guru
Posts: 8169
Joined: Tue Oct 19, 2004 6:44 pm
Location: Fernie British Columbia, Canada

Re: CROP news file upload

Post by calguy1000 »

a: What you are trying to do will not work with an <input type="file"> because for security purposes you cannot meddle with the value of this field. That is a javascript/browser specification.
b: The NewsArticleAdded/NewsArticleEdited events will not do what you want because they fire too late. After the data is already saved to the database.
c: You are left with storing the data-uri in a text/hidden field... but there you have a size limitation of 64k.

To remove that limitation, to convert the data-uri back to an image file, or do other things, and/or to make it so that you could hook into the 'editarticle' routine earlier would require a code modification.
Follow me on twitter
Please post system information from "Extensions >> System Information" (there is a bbcode option) on all posts asking for assistance.
--------------------
If you can't bother explaining your problem well, you shouldn't expect much in the way of assistance.
pWorker
Forum Members
Forum Members
Posts: 48
Joined: Wed Aug 31, 2016 1:30 pm

Re: CROP news file upload

Post by pWorker »

Hi,

thanks for your responses.

Well, as i could understand so far, i would have to manipulate the action.editarticle.php file, and there, i have to adjust the logic for the custom fields.

Is it possible to set the value of a specific custom_field (type multipart) (if isset) to be the src attribute of a e.g. div box (and could i simply add it here when prompt == xy && if isset)?

Code: Select all

        //
        //Update custom fields
        //

        // get the field types
        $qu = "SELECT id,name,type FROM " . CMS_DB_PREFIX . "module_news_fielddefs WHERE type='file'";
        $types = $db->GetArray($qu);

        $error = false;
        if (is_array($types)) {
            foreach ($types as $onetype) {
                $elem = $id . 'customfield_' . $onetype['id'];
                if (isset($_FILES[$elem]) && $_FILES[$elem]['name'] != '') {
                    if ($_FILES[$elem]['error'] != 0 || $_FILES[$elem]['tmp_name'] == '') {
                        $error = $this->Lang('error_upload');
                    } else {
                        $error = '';
                        $value = news_admin_ops::handle_upload($articleid, $elem, $error);
                        $smarty->assign('checking', 'blah');
                        if ($value !== FALSE)
                            $params['customfield'][$onetype['id']] = $value;
                    }
                }
            } // foreach
        }// if
What i do not understand, when i regularily select a file and press submit, the file is uploaded to my uploads/news/id etc. folder, so the information sent to the db seems to be only a link to that file on my webspace folder. Why isn't it possible to save (via click) the base64 img as a decoded .jpg file on webspace and just send a link to the db, with the src path of my saved image under the prompt of a specific custom field?

Or is it possible to store that image via the content_entry, which is also unique for each article and seems to support custom_content?

I really have to find a solution, can`t say my boss it isn`t possible to crop images with this cms...so, are there agencies you know, or perhaps youself, who i could pay for finding a solution? Or whom would i have to ask for implementing such a function, a php programmer? Would he be fit in cmsms environment or has it to be a cmsms specialist?

Can`t believe, that i`m the only one who needs a cropping functionality...
User avatar
velden
Dev Team Member
Dev Team Member
Posts: 3313
Joined: Mon Nov 28, 2011 9:29 am
Location: The Netherlands

Re: CROP news file upload

Post by velden »

For commercial support you could post in viewforum.php?f=34 or submit your erquest here: https://www.cmsmadesimple.org/support/hire-a-dev/

Another idea: why don't you allow the submission of the original image and send the cropping coordinates in other fields. Then use that data to manipulate the uploaded image server-side?

Only disadvantage I can think of is the upload of large files. But after upload you can do whatever you like with the original image.
pWorker
Forum Members
Forum Members
Posts: 48
Joined: Wed Aug 31, 2016 1:30 pm

Re: CROP news file upload

Post by pWorker »

Hey velden,
Another idea: why don't you allow the submission of the original image and send the cropping coordinates in other fields. Then use that data to manipulate the uploaded image server-side?
that would be the top solution, because:

I need the cropped image only as preview image, and the original one as whole articlepic.

Can`t i just set the max upload file size restriction then or adjust the upload module settings, so that dina 0 pngs initially can`t be submitted/ uploaded ore are being resized?

A last question, before looking around for commercial support:

How and where would you implement the serverside script (that it gets the coords and makes the cropping inserting it as field value?) in the action php script?

Thx so far!
User avatar
velden
Dev Team Member
Dev Team Member
Posts: 3313
Joined: Mon Nov 28, 2011 9:29 am
Location: The Netherlands

Re: CROP news file upload

Post by velden »

How and where would you implement the serverside script (that it gets the coords and makes the cropping inserting it as field value?) in the action php script?
I would certainly NOT change any script (btw: we do not allow posting about 'hacks' in this forum anyway).

Either use a UDT together with the Events (mentioned earlier) or check CGSmartImage module help. It has crop functionality but I don't know if you can give it exact coordinates etc. If it doesn't, consider asking the module developer (Calguy) if he's willing to implement such a features and at what costs.

Advantages of CGSmartImage: it does all work for you; processing image, caching results (keeping original image available) etc. etc.
calguy1000
Support Guru
Support Guru
Posts: 8169
Joined: Tue Oct 19, 2004 6:44 pm
Location: Fernie British Columbia, Canada

Re: CROP news file upload

Post by calguy1000 »

If I were to do this I would do it using a text field in the News module.

First I would increase the size of the appropriate column in the database to longtext.
Next I would use my javascript foo to create a data-uri of the cropped image and store it in the appropriate input field in the form. Either modifying the edit article template to make it a hidden field, or hiding the field with css.
Then on submit validate that the field is either empty, or at least appears to contain a data-uri to an image.

Your summary and detail views are then simple... as you know that that special field will either be empty or contain an image data-uri and you can display it in a normal img tag.

So there's no real PHP modification needed. A possible database modification, and then some javascript skills needed.
Follow me on twitter
Please post system information from "Extensions >> System Information" (there is a bbcode option) on all posts asking for assistance.
--------------------
If you can't bother explaining your problem well, you shouldn't expect much in the way of assistance.
pWorker
Forum Members
Forum Members
Posts: 48
Joined: Wed Aug 31, 2016 1:30 pm

Re: CROP news file upload

Post by pWorker »

Hey friends,

there is a fatal error in my hdd, so i have to use a rent pc for the next days... (perfectly timed).

It sounds doable. I`ll give it a try by myself, otherwise i`m going to spend money.

While i was waiting for my pc to be fixed, i did research about cg smartimage. Isn`t it possible (how is it possible) to save the crop data as img file (everytime with same name ->overwriting old) in the specific news id subfolder folder? Then i could use a cgsmartimage tag to load the cropped file {if isset}. So the solution is quite easy, all i had to do is to save the cropped data url as img file when i press submit and then enter

Code: Select all

{CGSmartImage src='uploads/images/news/{$category_id}/cropimage/'}
in my news detail template-haven`t got right path in my head- or am i misunderstanding sth? -Isn`t it possible for some reasons?

It`s a complex theme, but i`m highly interested in an efficient solution (also doable for average skilled users ;) )

Thanks is advance
User avatar
velden
Dev Team Member
Dev Team Member
Posts: 3313
Joined: Mon Nov 28, 2011 9:29 am
Location: The Netherlands

Re: CROP news file upload

Post by velden »

CGSmartImage stores the images with a specific name and location you can not set.

But you don't need to know because CGSmartImage knows it. Just call CGSmartImage tag with the image location of the original image and other parameters and things will work.
Locked

Return to “Modules/Add-Ons”