tags:

views:

128

answers:

4

I'm designing a template creation tool, which uses a jQuery Ajax request that posts parameters to a PHP file. The PHP does the actual generation of the template's HTML.

// Send for processing. Expect JS back to execute.
function generate() {
$.ajax({
    type: "POST",
    url: "generate.php",
    data: $('#genform :input').serialize(),
    dataType: "script",
    beforeSend: function() {
        $("#loading").html("<img src='images/loadbar.gif' />");
        $("#loading")           
        .dialog({
            height: 80,
            width: 256,
            autoOpen: true,
            modal: true
        });
    },
    success: function(data) {
        $("#loading").dialog('close');
    }
});
}

My trouble is that I have the ajax dataType: set to "script". Using this, the PHP file generates some jQuery dialogs for any errors which works nicely. However, after I generate the HTML, i'm having trouble passing it back.

So I have probably 100 lines of generated HTML and javascript which i'd like to work with. In the PHP file, i've tried:

echo('$("#result").html("'.$html.'");');

This does actually work if there are NO line breaks in $html. As soon as there are any line breaks, the Chrome debugger reports "gen.html:1 Uncaught SyntaxError: Unexpected token ILLEGAL". It's obvious that it's trying to eval the returned response headers, but is stopping at any line break.

So, to be clear, when I pass $html back, if the contents are this:

$html = "<div>hi there</div>";

It works fine (all of my error message dialogs are one line). But if it's:

$html = "<div>
           hi there
         </div>";

It blows up.

I'm really not sure how to get around this, or if there's a better way to go about it. It's important to me to keep the formatting so people can copy the HTML template.

I may just break down and display the template file on the PHP page if I can't solve this, but I was really hoping to keep everything within the confines of the HTML page.

A: 

You can change the dataType to 'text' or 'xml' so that the response is not evaluated.

dataType: ($.browser.msie) ? "text" : "xml",
Dave
That's certainly one way to go, though I perform different actions based on if there is an error (show dialog) or if the template is displayed ( $("#result").html("..."); ). If I just echo out all responses, I lose that control.
Rendrik
To get around this, you can handle Exceptions and output actual HTTP Errors (using headers), which will be sent back to your ajax call as an XHRError which you can easily handle.
FilmJ
I haven't explored that yet, but it sounds good. So basically if there's a problem, I can make up my own HTTP header (I think they only go up to 505?). Then if i'm getting you correct, i'd add the "complete" ajax callback, since it gets the XMLHttpRequest object (I think), and go from there?
Rendrik
A: 

You have to escape everything that would break the javascript code:

$html = str_replace(array('\\', "\r", "\n", '"'), array('\\\\', '\r', '\n', '\"'), $html);

echo('$("#result").html("'.$html.'");');

Marek
A: 

Try create output handler function:

function ob_handler($string, $flags) {
    return nl2br($string);
}

Or:

function ob_handler($string, $flags) {
    $string = str_replace(array("\r", "\n"), array('', ''), $string);
    return $string;
}

And then use it your code:

ob_start('ob_handler');
/// all your code here
ob_end_flush();
Zyava
A: 

Another simple way (similar to the xml solution) is to have a JSON response encoded as an object. This is naturally supported by jQuery, which actually decodes the JSON for you as well. It involves using:

  1. Replace dataType: "script" with datatype: "json"
  2. Change the success function to do the html replacement.
  3. Change the PHP to simply output the json_encode($html);

Here's the changed success function

success: function(data) {
    $("#loading").dialog('close');
    $("#result").html(data.result_html);
}

Here's the changed PHP function:

echo json_encode(array('result_html' => $html));

I prefer not to directly output the HTML so you can add extra data to the JSON output in the future, but you can also simply do $("#result").html(data); with the PHP echo json_encode($html);

phsource