Ошибка JavaScript при передаче html в JSON-пакет - PullRequest
0 голосов
/ 12 апреля 2011

Я схожу с ума, пытаясь решить эту проблему.Я реализовал Ajax-загрузку файлов, похожую на Coldfusion, которая загружает файл, используя скрытый фрейм, а затем захватывает содержимое, возвращенное фреймом.Это основано на этой статье: http://www.bennadel.com/blog/1244-ColdFusion-jQuery-And-AJAX-File-Upload-Demo.htm

Итак, все работает отлично, ЗА ИСКЛЮЧЕНИЕМ, когда я отправляю обратно HTML в данных.Итак, если вы посмотрите на код ниже, я предоставил страницу действий, которая передает данные обратно в скрытый фрейм.Первая строка работает, вторая строка с html - нет.

    <!--- Create the return HTML. Remember, we are going to be treating the BODY of the returned document as if it were a JSON string. --->
    <cfsavecontent variable="strHTML">

        <cfset var sResponse = {} />
        <!--- THIS WORKS --->
        <cfset sResponse = {SUCCESS = true, ERRORS = [], DATA = "Hello World", RETURNID=""} />
        <!--- THIS DOES NOT WORK --->
        <cfset sResponse = {SUCCESS = true, ERRORS = [], DATA = #HtmlEditFormat('<div>Hello World</div>')#", RETURNID=""} />

        <cfoutput>
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html>
            <head></head>
            <body>#SerializeJSON( sResponse )#</body>
            </html>
        </cfoutput>
    </cfsavecontent>

<!--- Create binary response data. --->
<cfset binResponse = ToBinary( ToBase64( strHTML ) ) />

<!--- Tell the client how much data to expect. --->
<cfheader name="content-length" value="#ArrayLen( binResponse )#" />

<!--- Stream the "plain text" back to the client .--->
<cfcontent type="text/html" variable="#binResponse#" />

Javascript для выполнения всего этого ниже.Строка с ошибкой при возврате HTML:

// Предполагая, что наши возвращаемые данные в формате JSON, оцените тело html, чтобы получить наши возвращаемые данные.var objData = eval ("(" + jBody.html () + ")");

//ShareForm Photo Upload Form Process (simulated Ajax)
$(document).ready(function() {
    // Attach an event to the submit method. Instead of submitting the actual form to the primary page, we are going to be submitting the form to a hidden iFrame that we dynamically create.
    $( "#frmShareForm" ).submit(
        function( objEvent ){
            var jThis = $( this );
            var photoUploadAction = $("#photoUploadAction").val();

            // Create a unique name for our iFrame. We can do this by using the tick count from the date.
            var strName = ("uploader" + (new Date()).getTime());

            // Create an iFrame with the given name that does not point to any page - we can use the address "about:blank" to get this to happen.
            var jFrame = $( "<iframe name=\"" + strName + "\" src=\"about:blank\" />" );

            // We now have an iFrame that is not attached to the document. Before we attach it, let's make sure it will not be seen.
            jFrame.css( "display", "none" );

            // Since we submitting the form to the iFrame, we will want to be able to get back data from the form submission. 
            // To do this, we will have to set up an event listener for the LOAD event of the iFrame.
            jFrame.load(
                function( objEvent ){
                    // Get a reference to the body tag of the loaded iFrame. We are doing to assume that this element will contain our return data in JSON format.
                    var objUploadBody = window.frames[ strName ].document.getElementsByTagName( "body" )[ 0 ];

                    // Get a jQuery object of the body so that we can have better access to it.
                    var jBody = $( objUploadBody );

                    // Assuming that our return data is in JSON format, evaluate the body html to get our return data.
                    var objData = eval( "(" + jBody.html() + ")" );
                    alert(objData);

                    // A JSON-format struct is returned that will be used to do callback functionality
                    SharePhotoAjaxResponseHandler(objData);

                    // Remove the iFrame from the document. Because FireFox has some issues with "Infinite thinking", let's put a small delay on the frame removal.
                    setTimeout
                    (
                        function()
                        {
                            jFrame.remove();
                        }, 100
                    );
                }
            );

            // Attach to body.
            $( "body:first" ).append( jFrame );

            // Now that our iFrame it totally in place, hook up the frame to post to the iFrame.
            jThis
                .attr( "action",  photoUploadAction)
                .attr( "method", "post" )
                .attr( "enctype", "multipart/form-data" )
                .attr( "encoding", "multipart/form-data" )
                .attr( "target", strName );
    });
});

Яваскрипт, который я получаю, обычно выглядит примерно так: «литерал не определенного регулярного выражения»

Я также попытался удалить SerialiseJson на странице CFM и eval в javascript, что приводит к другим ошибкам js.Я также попытался удалить окружающий html, а также изменить .html () на .text (), удалить eval () и их комбинации.Не повезло.

Пожалуйста, кто-нибудь может сказать мне, в чем проблема.Я знаю, что не могу быть далеко, так как он работает без HTML.

Спасибо

ОБНОВЛЕНИЕ: я запустил вывод JSON, который Coldfusion генерирует через валидатор JSON, и он не состоялся из-за (насколько я вижу) двойных кавычек:

{""RETURNID"":"""",""DATA"":""&lt;div&gt;Hello World&lt;\/div&gt;"",""SUCCESS"":true,""ERRORS"":[]}

Теперь я действительно не знаю, почему Coldfusion делает двойные кавычки ??У кого-нибудь есть идеи?

Ответы [ 4 ]

2 голосов
/ 12 апреля 2011

HTML-ответ интерпретируется как искаженный HTML.SerializeJSON экранирует "/" в "</div>" как "<\/div>", в результате чего анализатор HTML видит некорректный HTML.На стороне javascript "/div" выглядит как неправильное регулярное выражение.

Чтобы это работало, вы должны заставить браузер не интерпретировать данные для вас.Отправляйте данные как в блоке скрипта с неверным типом (поэтому браузер не запускает скрипт).

В Coldfusion:

<!--- Create the return HTML. Remember, we are going to be treating the BODY of the returned document as if it were a JSON string. --->
<cfsavecontent variable="strHTML">

    <cfset sResponse = {SUCCESS = true, ERRORS = [], DATA = "<div>Hello World</div>", RETURNID=""} />
    <cfoutput>
        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        <html>
        <head></head>
        <body><script id="data" type="json">#SerializeJSON( sResponse )#</script>
        </html>
    </cfoutput>
</cfsavecontent>

<!--- Create binary response data. --->
<cfset binResponse = ToBinary( ToBase64( strHTML ) ) />

<!--- Tell the client how much data to expect. --->
<cfheader name="content-length" value="#ArrayLen( binResponse )#" />

<cfcontent type="text/html" variable="#binResponse#" />

В браузере jsonисточник найден с помощью

var objUploadBody = window.frames[ strName ].document.getElementById( "data" );

// Get a jQuery object of the body so that we can have better access to it.
var jBody = $( objUploadBody );

// Assuming that our return data is in JSON format, evaluate the body html to get our return data.
var objData = eval( "(" + jBody.html() + ")" );
0 голосов
/ 12 апреля 2011

Вы добавляете JSON в <body> HTML-документа.

Браузер будет интерпретировать его как HTML и выполнять над ним исправление ошибок (например, конвертировать & в &amp; и отбрасывать элементы, которые не разрешены в местах, где вы их поместили.

Затем вы извлекаете его, используя метод html() jQuery, который будет получать исходный текст HTML, а не нужный вам текст.

Таким образом, решение:

  1. Кодировать любые объекты в JSON. Вам нужно HTML-представление строки JSON, а не необработанная строка. Я не знаю, как это сделать в CF, но должен быть эквивалент encode_entities / htmlspecialchars / etc
  2. Получите text(), а не html()

(Кстати: это все, что вам нужно сделать, а не список альтернатив)

0 голосов
/ 12 апреля 2011

Проблема в том, что вы встраиваете ответ JSON с сервера в большее количество html. Ответ JSON для вызова AJAX должен содержать ONLY текст JSON и ничего больше.

Поскольку вы встраиваете его в HTML, а затем извлекаете его с помощью вызова DOM, скорее всего, браузер полностью запутывается вашим html внутри json в html и искажает DOM.

Попробуйте вместо этого:

<cfoutput>#SerializeJSON( sResponse )#</cfoutput>

и

var objData = eval(jBody);

хотя, как отмечали другие отвечающие, вам не следует использовать eval для этого. Есть гораздо более безопасные способы анализа данных JSON обратно в объекты javascript, чем eval.

0 голосов
/ 12 апреля 2011

Ошибка JavaScript, которую я получаю, обычно что-то вроде: выражение буквальное "

Проверьте свой JSON. Вы можете запустить его, хотя JSONLint , чтобы увидеть, является ли он действительным или нет. Возможно, это не так, на основании вашего сообщения об ошибке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...