Search code examples
phpjquerysmartyplupload

Plupload: get data attributes of multiple dynamic dropzones


I am working on a project where we are using a single instance of plupload to handle the uploads from multiple dropzones that are dynamically generated. We use Smarty templates, jQuery and PHP. There are a couple attributes that need to be carried over throughout the process as once the upload to the server hosting the application is successful, a transfer of the documents happens, transferring the document to AWS. I am struggling to understand how I can collect the need attributes during the initial upload through plupload. Currently, the files upload fine to the local server.

What I need is to get the id of the row, and the data-type attribute of the dropped-on row. You can see in the opening li the attributes id={$doc.id} and data-type={$doc.id}; these are the attributes I need to collect. Here is the markup for the form:

{foreach $document_set as $doc}
    <li id="file-{$doc.id}" class="doc_list_row" data-type="{$doc.id}">
        <div class="row doc_list_row">
            <div class="col-sm-12" style="color: #fff">
                <div class="row">
                    <div class="col-sm-12 doc_list_title">
                        <h4>{$doc.name}</h4>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-8">
                    <div class="row">
                        <div class="col-sm-8 padtop-10">
                            <p>{$doc.description}</p>
                        </div>
                    </div>
                    <div class="row file_details_row">
                        <div class="col-sm-6">
                            <h4>Created On:</h4>
                            <p>{$doc.created}</h4>
                        </div>
                        <div class="col-sm-6">
                            <h4>Created By:</h4>
                            <p>{$doc.created_by}</p>
                        </div>
                    </div>
                    <div class="row file_details_row">
                        <div class="col-sm-6">
                            <h4>Updated On:</h4>
                            <p>{$doc.last_update}</h4>
                        </div>
                        <div class="col-sm-6">
                            <h4>Updated By:</h4>
                            <p>{$doc.last_update_by}</p>
                        </div>
                    </div>
                </div>
                <div class="col-sm-4 mng_file_icon_container">
                    <div class="row">
                        <div id="dl-{$doc.id}" class="col-xs-6 col-sm-6 dl_icon" data-filename="fileURLWillGoHere">
                            <div id="dl_circle-{$doc.id}" class="dl_circle circle">
                                <div class="triangle-down">
                                </div>
                                <h3 class="dl_version">V.{$doc.version_depth}</h3>
                            </div>
                        </div>
                        <div class="col-xs-6 col-sm-6 upld_icon" data-toggle="modal" data-target="#upld_file_modal">
                        <div id="upld_circle-{$doc.id}" class="upld_circle circle">
                            <div class="triangle-up">
                            </div>
                            <h3 class="upld_version">V.{$doc.version_depth + 1}</h3>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</li>
{/foreach}

Here is the jQuery to handle this handoff:

var dom = { uploader: $("#dropbox"), 
            uploads: $("ul.doc_list_container"), 
            dropzones: $("li.doc_list_row")
};

uploader = new plupload.Uploader({
    runtimes : "html5,silverlight,html4",
    browse_button : "file-pick",
    container : "file-cntr",
    max_file_zie : '10mb',
    url : "../upload.php",
    drop_element: "dropbox",
    filters : {title : "Text Files", extensions : "pdf, doc, docx, xls, xlsx, ppt, pptx"},
    init: {
        FilesAdded: function(up, files){ up.start(); $("#file-upld-progress").fadeIn(300); },
        UploadProgress: function(up, file){ $("#file-upld-progress").text(file.percent + "%"); },
        UploadComplete: function(up, file) { $("#file-upld-progress").fadeOut(300, function(){ setTimeout(function(){ $("#file-upld-progress").text(''); }, 2500); }); },
        FileUploaded: function(up, file, resp, src) { uploadHandler(resp.response, src); },
        Error: function(up, err) { showFormMsg("alert-error", "File Upload Error #" + err.code + ": " + err.message); }
    },
    multipart: true,
    multipart_params : {}
});

uploader.bind("BeforeUpload", handlePluploadBeforeUpload);
uploader.bind("PostInit", handlePluploadInit);
uploader.bind("FilesAdded", handlePluploadFilesAdded);
uploader.init();
uploader.bind("FileUploaded", function(up, file, resp) { uploadHandler(resp.response); });

var fileType = '';
dom.dropzones.each(function(){
    var dropzone = new mOxie.FileDrop({
        drop_zone: $(this).attr('id')
    });

    dropzone.ondrop = function(e){
        uploader.addFile(this.files);
        // fileType = $(this);
    };

    dropzone.init();

    var input = new mOxie.FileInput({
        browse_button: $("#file-pick")[0],
        container: this,
        multiple: true
    });

    input.onchange = function(e){
        uploader.addFile(input.files);
    };

    input.init()
});

function handlePluploadBeforeUpload( uploader, file ) {
    params = uploader.settings.multipart_params;
    var source = file.getSource();
    // console.log(source);
    // console.log(params.docType);
}


function handlePluploadInit(uploader, params){
    // console.log("Initialization complete.");
    // console.log("Drop-drop supported:", !! uploader.features.dragdrop);
}

function handlePluploadFilesAdded( uploader, files ) {
    for ( var i = 0 ; i < files.length ; i++ ) {
        files[i].docType = $(this).data('type');
    }
}

And upload.php:

<?php
session_start();
require_once(dirname(dirname(__DIR__)).'/sites/site_settings.php');

//Output passed values from plUpload
/*$fh = fopen("./request.txt",'w');
fwrite($fh, "Request Dump\n");
fwrite($fh, print_r($_REQUEST, true));
fwrite($fh, "\n\nPost Dump\n");
fwrite($fh, print_r($_POST, true));
fwrite($fh, "\n\nGET Dump\n");
fwrite($fh, print_r($_GET, true));
fwrite($fh, "\n\nServer Dump\n");
fwrite($fh, print_r($_SERVER, true));
fwrite($fh, "\n\nFiles Dump\n");
fwrite($fh, print_r($_FILES, true));
fclose($fh);*/

if($_SERVER['REQUEST_METHOD'] == "POST")
{
    if(! empty($_FILES['file']))
    {
        if($_FILES['file']['error'] === UPLOAD_ERR_OK)
        {
            $path_info = pathinfo($_FILES['file']['name']);
            $file_extension = strtolower($path_info["extension"]);
            $extension_whitelist = array("pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx");
            $doc_fk = $_FILES['file']['doc_fk'];
            if(in_array($file_extension, $extension_whitelist))
            {
                try
                {
                    $url = ADMIN_URL."/documents/temp/";
                    $path = ADMIN_PATH."/documents/temp/";
                    $fname = cleanFilename($_FILES['file']['name']);
                    if(move_uploaded_file($_FILES["file"]["tmp_name"], $path.$fname))
                        $ret = array("error" => 0, "path" => $url, "givenName" => $_FILES['file']['name'], "storedName" => $fname, "ext" => $file_extension, "doc_fk" => $doc_fk);
                    else
                        $ret = array("error" => 1, "error_msg" => "Failed to Upload File to System");
                }
                catch(Exception $e)
                {
                    $ret = array("error" => 1, "error_msg" => $e->getMessage());
                }
            }
            else
                $ret = array("error" => 1, "error_msg" => "Invalid file type: $file_extension. File must be PDF, Word Document, Excel Spreadsheet or a PowerPoint Presentation.");
        }
        else
            $ret = array("error" => 1, "error_msg" => "Upload Error Occurred");
    }
}
else
    $ret = array("error" => 1, "error_msg" => "Failed POST check: ".$_SERVER[REQUEST_METHOD]);

echo json_encode($ret);

?>

Once I understand how to collect those two attributes, I will be able to move forward with completing this part of the project. This is the last hangup, and has absorbed several hours of trial and error, following a variety of GitHub articles, and SO threads. I've also referred to plupload's forums and haven't encountered anything quite similar to what we are doing here. TIA for any assistance!


Solution

  • Here's the solution we managed to come up with for our use case in this scenario. With our jQuery, we create an array of uploaders. This is where our dynamically generated uploader's id's will be stored. Then for each potential uploader, we instantiate a new uploader. Considering we iterate on the doc_list_row class, we are able to acquire the individual id of each list row, and place this in drop_element.

    Everything else from here south is essentially the same as a typical plupload instance.I included our uploadHandler function simply for reference, it is not necessary if you handle the upload success differently. Keep in mind we use smarty templates and xajax, so if you use standard ajax, or another language other than PHP for you backend, some of this code will not directly work for you! I hope this helps others in a similar situation figure out the next step as this use case was a bit difficult to conquer.

    jQuery

    /*******************************************************************************
    *
    * Upload Document
    *
    *
    *******************************************************************************/
    function initUploaders(){
        if($("li.doc_list_row").length){
            upldrs = new Array();
                $("li.doc_list_row").each(function(){
                    upld = new plupload.Uploader({
                    runtimes : "html5",
                    url : "upload.php",
                    dragdrop: true,
                    drop_element : $(this).attr("id"),
                    browse_button : $(this).find("div.upld_icon").attr("id"),
                    filters: {
                        max_file_size : '10mb',        
                        mime_types: [{title : "Scan Files", extensions : "pdf,jpg,jpeg,png,xls,xlsx,doc,docx"}]
                     },
                     multipart_params : {DOC_ID: $(this).attr("data-doc")}, 
                     init: {
                        // FilesAdded: function(up, files){ up.start(); },
                        FilesAdded: function(up, files){ up.start(); showProgressBar(up); },
                        UploadProgress: function(up, file){ $(".upld-progress").css("width", file.percent + "%"); },
                        UploadComplete: function(up, file) { hideProgressBar();      },
                        FileUploaded: function(up, file, resp) { uploadHandler(resp.response); },
                        Error: function(up, err) { showFormMsg("alert-error", "File Upload Error #" + err.code + ": " + err.message); }
                    }
                });
                upld.init();
                upldrs.push(upld);
            });
        }
    }
    
    
    /*******************************************************************************
    *
    * Response handler for plupload
    *
    *
    *******************************************************************************/
    function uploadHandler(resp){
        var r = $.parseJSON(resp);
        if(r.error)
            showFormMsg("alert-danger", "Upload Error: " + r.error_msg);
        else{
            var elemId = $(upld.settings.drop_element[0]).attr('id').split('-');
            showFormMsg('alert-success', 'Upload successful.');
            xajax_paginate(currentPage(), currentDept(), $("#filter-doc-category").val(), $("#search_doc_name-id").val().trim(), $("#search_publisher_name-id").val().trim());
            $("#file-"+elemId).find('.unavail_dl_icon').removeClass('unavail_dl_icon').addClass('dl_icon');
        }
    }
    

    HTML

    {if $documents_set|default:0}
    {foreach $documents_set as $doc}
    <li id="file-{$doc.id}" class="doc_list_row" data-doc="{$doc.id}" data-ondeck="0" data-default="{$doc.name}">
        <div class="row doc_list_row">
            <div class="col-sm-8">
                <div class="row">
                    <div class="col-sm-12 doc_list_title">
                        <div class="col-sm-3"><h4>{$doc.name}</h4></div>
                            <div class="col-sm-4" style="padding-top: 15px; margin-bottom: 0;">
                            <div id="doc-upld-bar-{$doc.id}" class="progress upld-progress">
                            <div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:100%"></div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-8">
                    <div class="row">
                        <div class="col-sm-8 padtop-10">
                            <p>{$doc.description}</p>
                        </div>
                    </div>
                    <div class="row file_details_row">
                        <div class="col-sm-6">
                            <h4>Last Update:</h4>
                            <p>{$doc.lastUpdate}</p>
                        </div>
                        <div class="col-sm-6">
                            <h4>Last Update By:</h4>
                            <p>{$doc.last_update_by}</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-sm-4">
            <div class="row">
                <div class="col-sm-12 mng_file_icon_container">
                    <div id="dl-{$doc.id}" class="col-xs-6 col-sm-6 {if $doc.file_list|default:''}dl_icon{else}unavail_dl_icon{/if}" data-doc="{$doc.id}">
                        <!-- This is the selector -->
                        {if $doc.file_list|default:''}
                        <select id="version-selector-{$doc.id}" class="available_versions">
                            {foreach $doc.file_list as $f}<option value="{$f}">{if $f@first}Current{else}{$f@index} Previous{/if}</option>{/foreach}
                        </select>
    
                        <div id="dl_circle-{$doc.id}" class="dl_circle circle" data-for="{$doc.file}">
                        <div class="triangle-down">
                        </div>
                    </div>
                    {else}
                    <select class="no_file" DISABLED>
                        <option>No File</option>
                    </select>
                    <div id="unavail_dl" class="unavail_dl_circle circle">
                    <div class="unavail_triangle">
                    </div>
                    </div>
                    {/if}
                </div>
                <div id="upld-{$doc.id}" class="col-xs-6 col-sm-6 upld_icon">
                <div id="upld_circle-{$doc.id}" class="upld_circle circle">
                    <div class="triangle-up">
                    </div>
                </div>
            </div>
        </div>
                </div>
            </div>
        </div>
    </li>
    {/foreach}