У меня есть запрос AJAX, который может иметь два возможных результата:
<div>
Каким будет решение, если у меня есть запрос AJAX, который должен обрабатывать оба этих случая?
url = "http://example.com" ajax.request(callback) function callback(response) { if (case2(response)) { history.pushState({}, "New page", url); document.innerHTML = response } else { updateDiv(response) } }
Я заинтересован в правильном способе реализации первой ветви, или если сервер может каким-то образом составить заголовки, которые заставят браузер обрабатывать ответ как обычный ответ HTTP и обновлять местоположение и содержимое страницы, что-то вроде перенаправления с данным контентом ,
Я понимаю, что сервер может возвращать ссылку вместо страницы, но в этом случае на клиенте потребуется дополнительный этап – перенаправление, а затем заполнение новой страницы на сервере.
Честно говоря, я думаю, что этот подход в основном нарушается дизайном. Вы не должны принимать это решение в этом месте. Например, ответ ajax может сигнализировать только о том, что необходимо загрузить всю новую страницу, а затем новый контент будет генерироваться во втором (не-ajax) запросе на новый URL-адрес.
В случае, если вы вынуждены пойти по пути, который вы уже прошли, и при условии, что контент ответа не очень велик, вы можете попробовать Javascript-URI. В принципе, URI в виде javascript:"string"
будет загружать новую страницу, для которой эта строка является исходным кодом. Итак, если response
уже является строкой, просто назначить javascript:response
to window.location.href
должно быть достаточно. Может быть, вам нужно немного ускользнуть. И я не знаю, как кросс-браузер-совместимый этот подход.
<a href="javascript:response">load</a>
также возможно.
Вариантом этого является создание URL-адреса не с именем переменной, а с фактическими строковыми данными. подобно
function source2url(src) { // make valid javascript string from source text var esc1 = src .replace(/\\/g, '\\\\') .replace(/\'/g, '\\\'') .replace(/\x0A/g, '\\x0A') .replace(/\x0D/g, '\\x0D'); // make valid url from that return "javascript:'" + encodeURIComponent(esc1) + "'"; } window.location.href = source2url(response);
Это, конечно же, приведет к созданию довольно больших URI. И вы всегда будете иметь Javascript-URI в адресной строке.
ОБНОВИТЬ
Аналогичный подход заключается в использовании кодирования base64 в URI данных. В записи в Википедии объясняется, как это работает, включая пример javascript. Тем не менее, вам нужно будет как -то закодировать содержимое base64 . (Примечание. Вы можете использовать URI данных с кодировкой base64 или без нее. Вы должны увидеть, что дает вам более короткие URI для вашего конкретного контента.)
Однажды у меня была аналогичная проблема. Была возвращена полная страница ошибки вместо простого фрагмента HTML. В конце концов мы установили это, изменив логику, но вот одно из решений, которые я нашел:
document.open(); document.write(responseText); document.close();
Причина, по которой мы отказались от этого, заключается в том, что на IE возникли некоторые проблемы. Я не терял времени, чтобы исследовать причину, но при попытке написать строку он выбрал исключение «Доступ запрещен». Я думаю, что есть теги <meta>
которые путают IE, или, может быть, условные комментарии, я не уверен. (Он работал, когда я использовал несколько простых страниц …)
Итог: вам не нужно это делать, но если вы ничего не можете сделать (например, вернуть строку url), код может работать.
Это очень просто, если ответ действительно является XML.
var new_doc = (new DOMParser).parseFromString(response, "application/xml"); document.replaceChild(document.adoptNode(new_doc.doctype), document.doctype); document.replaceChild(document.adoptNode(new_doc.documentElement), document.documentElement);
Поскольку запрос содержит обновленный ответ, вот мое решение, использующее API истории HTML5 с jQuery . Он должен работать легко, объединяя части PHP и HTML в один файл.
Мое решение позволяет AJAX возвращать следующее:
<div>
. history.pushState()
чтобы добавить текущий URL-адрес в историю браузера и заменяет весь HTML на странице HTML-кодом, возвращенным из AJAX. Это всего лишь образец того, что PHP-скрипт должен будет вернуть, когда он вызывается через AJAX. Он показывает, как кодировать флаги, чтобы определить, должен ли вызов AJAX обновлять контейнер или загружать новую страницу и как возвращать его результат через JSON через json_encode . Для полноты я назвал этот скрипт test.php .
<?php // Random messages to return $messages = array( 'Stack Overflow', 'Error Message', 'Testing' ); // If the page was requested via AJAX if( isset( $_POST['ajax'])) { $response = array( 'redirect' => // Flag to redirect ( rand() % 2 == 0) ? true : false, 'load_html' => // Flag to load HTML or do URL redirect ( rand() % 2 == 0) ? true : false, 'html' => // Returned HTML '<html><head><title>AJAX Loaded Title</title></head><body>It works!</body></html>', 'title' => 'History API previous title', 'message' => // Random message $messages[ (rand() % count( $messages)) ] ); echo json_encode( $response); exit; }
Поскольку я использую jQuery, давайте начнем с этого. Следующее отправляет AJAX POST на сервер, на указанный выше PHP-скрипт по адресу URL test.php . Обратите внимание, что он также устанавливает параметр POST ajax
как true
, позволяя скрипту PHP обнаруживать, что он получил запрос AJAX. Поле dataType
сообщает jQuery, что ответ сервера будет в JSON и что он должен декодировать этот JSON для объекта JSON в dataType
ответа. Наконец, обратный вызов success
, который запускается при успешном получении ответа AJAX, определяет, что делать на основе флагов, отправленных с сервера.
$.ajax({ type: 'POST', url: "/test.php", data: {ajax : true}, dataType: "json", success: function( json) { if( json.redirect) { if( json.load_html) { // If the History API is available if( !(typeof history.pushState === 'undefined')) { history.pushState( { url: redirect_url, title: document.title}, document.title, // Can also use json.title to set previous page title on server redirect_url ); } // Output the HTML document.open(); document.write( json.html); document.close(); } else { window.location = redirect_url; } } else { $('#message').html( json.message); } }, });
Вот полный источник HTML моего тестируемого файла. Я тестировал его в FF4 – FF8. Обратите внимание, что jQuery предоставляет ready
метод для предотвращения выполнения JS до загрузки DOM. Я также использовал хостинг Google jQuery, поэтому вам не нужно загружать копию jQuery на ваш сервер, чтобы проверить это.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js" type="text/javascript"></script> <title>Default Page</title> <script type="text/javascript""> $( document).ready( function() { $('#ajax_link').click( function() { var redirect_url = "/test.php"; $.ajax({ type: 'POST', url: "/test.php", data: {ajax : true}, dataType: "json", success: function( json) { if( json.redirect) { if( json.load_html) { // If the History API is available if( !(typeof history.pushState === 'undefined')) { history.pushState( { url: redirect_url, title: document.title}, document.title, // Can also use json.title to set previous page title on server redirect_url ); } document.open(); document.write( json.html); document.close(); } else { window.location = redirect_url; } } else { $('#message').html( json.message); } }, }); }) }); </script> </head> <body> <div id="message">The default contents of the message</div> <a id="ajax_link" href="#">Fire AJAX</a> </body> </html>
Дайте id телу <body id="page">
а ваш другой div будет <div id="message"></div>
теперь ваш аякс будет выглядеть так:
$.ajax({ url:'myAjax.php', data:{datakey:datavalue}, dataType:"JSON", success: function (response) { if(response.message=="your message") { $('#message').html(response.content); } else { $('#page').html(response.content); } } });
как говорит T-Bull … весь процесс здесь неправильный ….
вы просто чрезмерно усложняете вещи, и вы знаете, что infact:
Я понимаю, что сервер может возвращать ссылку вместо страницы, но в этом случае на клиенте потребуется дополнительный этап – перенаправление, а затем заполнение новой страницы на сервере.
перестаньте усложнять и начинайте делать это хорошо …
$_SESSION['tmp_client_id'] = 'client_'.session_id();
очевидно, лучше, если клиент уже подписан, во всяком случае, помещает материал в временную таблицу ИЛИ в другой сеанс var и т. д. … $_POST
внутри tmp_client_tbl
с ее уникальным tmp_client_id
ИЛИ просто $_SESSION['client_'.session_id()] = json_encode($_POST);
</div>
if( isset($_SESSION['client_'.session_id()])) {
если это так, давайте снова отобразим форму с заполненными полями: } else {
отобразить пустую форму; SELECT * FROM tmp_client_tbl WHERE tmp_client_id = '{$_SESSION['tmp_client_id']}'
ИЛИ json_decode($_SESSION['client_'.session_id()]);
$form_data = $mysql_rows;
ИЛИ $json_array;
foreach($form_data as $name => $value) { echo "<input name='$name' value='$value' />" }
в способе ниндзя, предполагающем, что у вас есть такой массив $form = array('text' => array('name','lastname'), 'select' => array('countries'), ... )
где $form = array('text' => array('name','lastname'), 'select' => array('countries'), ... )
, ИЛИ просто посредством <input name='lastname' value='{$lastname}' />
где значения полей предварительно распределены с пустыми vars; session_destroy();
или unset($_SESSION['client_'.session_id()]);