Posting Files via AJAX  Bottom

  • I have been playing around with my own gallery module - more as a mechanism to play with javascript and Ajax than any real need. One thing that I have been trying to do is to post a file upload (ie an image) via Ajax. I have it working to a extent - needs work, but I thought I would place it up here for others...

    The basic principle I used is as follows;

    1. Create a form with a submit and a file upload
    2. Call a javascipt function....this
    3. Creates an IFrame with the style as hidden
    4. Redirects the forms target to that IFrame
    5. Sets up an onLoad on the IFrame to call the response function.

    The response is just json. I process the image and return the HTML.

    Now!!!! This does not employ the standard AJAX.Request option. I don't know how to get that working

    In *My* case, this is a gallery - and I have a heap of blocks for images. So I create a block (div) for the new image with a "loading" icon and then replace that entire block's HTML with the newly formatted image HTML. Or an Error Message.

    I originally tried to post this as a single post, by I get an error back from DisKus...
  • The Form

    Code

    <form action="ajax.php?module=gallery&func=new&id=<!--[$id]-->&kind=I" method="post"
           enctype="multipart/form-data"
           onsubmit="return gallery_newimage(this);">
            <input type="hidden" name="blockid" id="blockid" value="HELLO">
            <table>
                <tr>
                    <td>Upload an Image</td>
                    <td><input type="file" name="filename" /></td>
                    <td><input type="submit" value="Upload" /></td>
                </tr>
            </table>
        </form>


    Here "id" is the gallery that the images goes into and "blockid" is a marker so I know what div to update later
  • The Function

    Code

    function gallery_newimage (theform) {
            var randtext = Math.floor(Math.random() * 99999);
            var blockid = "f" + randtext;
            var elementid = "e" + randtext;        
            myelement = document.createElement("li");
            myelement.setAttribute('class', "gallery_image_item");
            myelement.setAttribute('id', elementid);
            var blockhtml = '';
           
            myelement.innerHTML = '<img src="modules/gallery/pnimages/loading.gif"><div class="gallery_name_envelope">NEW IMAGE</div>' + blockhtml;
            mylist = document.getElementById('gallery_image_list');
            mylist.appendChild(myelement);

            theform.setAttribute('target', blockid);
           
            myhidden = document.getElementById('blockid');    
            myhidden.setAttribute("value", elementid);

            var i = document.getElementById(blockid);
            i.onComplete = gallery_newimage_response;
            return true;
            }


    Notice I assign the onComplete at the end as the IFrame loads twice - once when it is added and once when it is targeted by the form.
  • The Response

    I have done this in two parts

    Code

    function gallery_newimage_onload (suffix) {
            var i = document.getElementById("f"+suffix);
            if (i.contentDocument) {
                var d = i.contentDocument;
                }
            else if (i.contentWindow) {
                var d = i.contentWindow.document;
                }
            else {
                var d = window.frames["f"+suffix].document;
                }
            if (d.location.href == "about:blank") {
                return;
                }
            if (typeof(i.onComplete) == 'function') {    
                i.onComplete(d.body.innerHTML);
                }    
            }
  • This runs the second onLoad

    Code

    function gallery_newimage_response (response) {
            var json = pndejsonize(response);
            if (json.alert !== undefined) {
                alert(json.alert);
                }        
            if (json.error !== undefined) {
                alert(json.error);
                }
            if (json.oldid !== undefined) {
                myli = document.getElementById(json.oldid);
                if (json.html !== undefined) {
                    myli.innerHTML = json.html;
                    }
                else if (json.error !== undefined) {
                    myli.innerHTML = json.error;
                    }
                else {
                    myli.innerHTML = "Error";
                    }
                }
            }
  • The Ajax File

    Code

    function Gallery_Ajax_New () {

            $response = array();
           
            // -----------------------------------------------------------------------------
           
            $oldid = FormUtil::GetPassedValue("blockid");                
            $response["oldid"] = $oldid;


            // -----------------------------------------------------------------------------
            // Security

            if (!SecurityUtil::checkPermission("docs::", "::", ACCESS_ADD)) {
                $response["error"] = "No Permissions";
                }

            // -----------------------------------------------------------------------------

            else {

                do work here ....
               
                }

            // -----------------------------------------------------------------------------

            if (!is_null($response["error"])) {    
                $response["html"] = pnModAPIFunc("gallery", "user", "errorhtml", $response["error"]);    
                }

            // -----------------------------------------------------------------------------

            AjaxUtil::Output($response);
            }
  • This works fine...though I have run into an interesting issue.

    When I use pnRender to render the block for the image, the commands all fall out of the json string and I get an illegal json message....

    Other than that the concept works fine.
  • As an extension to this, I have run into an interesting problem where I have HTML encoded as a JSON variable and posted to a form - rather than collected as a response directly. I still have not worked out how to solve this. As long as the variables in the JSON do NOT have any HTML entities in them, the above will work.

    As soon as you use an HTML entity, the open/start tags within the JSON will have close tags appended to the innerHTML. Or, what I am saying is this;

    My response from the pnajax file is

    Code

    $output["html"] = "<div>hello</div>";
    AJAXUtil::Output($output);


    This is posted to an IFRAME. If you check the source of the IFRAME it is correct

    Code

    {"html":"<div>hello>/div<"}
    span>


    Notice the first tag is not encoded

    But when I alert the innerHTML I get

    Code

    {"html":"<div>hello>/div<"}</div>


    The DIV has been appended and this causes an error

    I have tried HTMLSpecialChars, an extra json_encode and a few other things. No solution yet?



    edited by: geoff, Jul 03, 2009 - 01:42 PM

This list is based on users active over the last 60 minutes.