LINUX.ORG.RU

При получении HTML через AJAX отображаются теги. Почему?

 , , , ,


0

1

Есть древовидная структура, раскрывающаяся +/-. В ней должны быть таблицы. Работаю с twig, через $twig->render данные для таблиц передаются в шаблон, итоговый HTML запоминается в ассоциативный массив. Кроме HTML в массиве еще всякие служебные значения вроде id и parent_id. Массив передается с сервера через JSON аяксом (jquery). Используется библиотека jqTree для построения дерева. Так вот, мне вместо таблицы отображается следующее

<table> <tr> <td>3</td> <td>Название</td> <td>Описание</td> <td></td> </tr> </table>

Т.е. html код этой таблицы.

Похоже, где-то экранируются теги. точно не twig - если выводить из шаблона без аякса одну табличку - все норм. Виноват либо json_encode в php либо jqTree либо функция getJSON в jquery.

Может кто сталкивался? Подскажите, что делать?

★★★★★

Последнее исправление: Qwentor (всего исправлений: 1)

Виноват jqTree - только что проверил. Без него 1 табличка через аякс передается((

Qwentor ★★★★★
() автор топика

Здравствуйте. Да, это json_encode. Вообще-то это не совсем правильно, передавать html внутри json-объекта, но если уж вам так этого хочется, воспользуйтесь JSON-константами.
Для вашего случая, это JSON_HEX_QUOT и JSON_HEX_TAG, но там есть и другие, то есть на сервере

echo json_encode(
    array('test' => 'YOUR_HTML'), 
        JSON_HEX_QUOT | JSON_HEX_TAG
    );
А на клиенте, если у вас jQuery, как вы сказали, то parseJSON
jQuery.ajax({
    url: 'url',
    method: 'GET',
    success: function(response) {
        var response = jQuery.parseJSON(response);
	console.log(response.test);
    }
});
Также, ЕМНИП, у .ajax есть свойство type, куда можно также указать JSON. Но как ни крути, передавать html в json-объекте, не лучшая практика :)

znenyegvkby
()
Ответ на: комментарий от znenyegvkby

Не похоже на json_encode, т.к. если убрать дерево (jqtree) и передавать одну табличку аяксом - все работает

Qwentor ★★★★★
() автор топика
Ответ на: комментарий от Qwentor

Не похоже на json_encode, т.к. если убрать дерево (jqtree) и передавать одну табличку аяксом - все работает

Ну все правильно, ибо JqTree на вход приходят неправильно расрас JSON-на, вот и получается белиберда на выходе :) Я сейчас быстренько проверил на своем сервачке

echo json_encode(
    array('test' => '<div style="width: 100px; height: 100px; background: red"></div>')
    );
Ни getJSON, ни parseJSON, ни type: 'JSON' у .ajax не могут распрарсить мне нормально HTML, ибо он невалидный (экранирован после json_encode)
echo json_encode(
    array('test' => '<div style="width: 100px; height: 100px; background: red"></div>'),
    JSON_HEX_QUOT | JSON_HEX_TAG
    );
При такой отдаче, все символы преобразуются в HEX, и любой parserJSON/getJSON/etc парсит HTML без проблем.

znenyegvkby
()
Ответ на: комментарий от Qwentor

Если можно еще: заголовки ответа сервера.
+ версию PHP, ибо эти константы работают только с версии 5.3.0 и выше. Проверить это можно, посмотрев ответ сервера, если символы «<» «>» или двойная кавычка не перекодированы, значит константы не срабатывают.

znenyegvkby
()
Ответ на: комментарий от znenyegvkby

Как отправляю:

<?php
require_once 'vendor/autoload.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem('templates');
$twig = new Twig_Environment($loader, array(
    'cache' => 'compilation_cache',
));

$servername = "localhost";
$username = "root";
$password = "random123";
$dbname = "onepage";

$conn = mysqli_connect($servername, $username, $password, $dbname) or die("Connection failed: " . mysqli_connect_error());

if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$sql = "SELECT * FROM tables ORDER BY parent_id DESC";
$res = mysqli_query($conn, $sql) or die("database error:". mysqli_error($conn));
$data = mysqli_fetch_all($res, MYSQLI_ASSOC);

foreach ($data as $key => &$value) {

	$value['id'] = (int)$value['id'];
	$value['label'] = $twig->render('tables.twig', $value);



	foreach ($data as &$value2) {
		if($value['parent_id'] == $value2['id']){
			
			$value2['children'][] = $value;
			unset($data[$key]);

		}
	}

}

$data = array_values($data);

unset($value);
unset($value2);

echo json_encode($data);


Qwentor ★★★★★
() автор топика
Ответ на: комментарий от Qwentor

А теперь, подставьте константы в json_encode и запостите ответ в чистом виде, то есть не через getJSON/parse/etc, а обратитесь к скрипту, напрямую, через браузер или консоль, и ответ сюда, вместе с заголовками, если можно.
P.S. только сделайте плиз в селекте LIMIT 0,1, чтобы не было портянок, ну или на pastebin.

znenyegvkby
()
Ответ на: комментарий от Qwentor

Ничего не меняется в ответе? Вы точно ответы в чистом выводе смотретите, а не после getJSON'на?

znenyegvkby
()
Ответ на: комментарий от znenyegvkby

Ответ с константами:

[{"id":1,"number":"1","name":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","parent_id":"0","label":"\u003Ctable\u003E\n\t\u003Ctr\u003E\n\t \u003Ctd\u003E1\u003C\/td\u003E\n\t \u003Ctd\u003E\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u003C\/td\u003E\n\t\u003C\/tr\u003E\n\u003C\/table\u003E"},{"id":2,"number":"2","name":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","parent_id":"0","children":[{"id":3,"number":"2.1","name":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","parent_id":"2","label":"\u003Ctable\u003E\n\t\u003Ctr\u003E\n\t \u003Ctd\u003E2.1\u003C\/td\u003E\n\t \u003Ctd\u003E\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u003C\/td\u003E\n\t\u003C\/tr\u003E\n\u003C\/table\u003E"},{"id":4,"number":"2.2","name":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","parent_id":"2","children":[{"id":5,"number":"2.2.1","name":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","parent_id":"4","label":"\u003Ctable\u003E\n\t\u003Ctr\u003E\n\t \u003Ctd\u003E2.2.1\u003C\/td\u003E\n\t \u003Ctd\u003E\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u003C\/td\u003E\n\t\u003C\/tr\u003E\n\u003C\/table\u003E"},{"id":6,"number":"2.2.2","name":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","parent_id":"4","label":"\u003Ctable\u003E\n\t\u003Ctr\u003E\n\t \u003Ctd\u003E2.2.2\u003C\/td\u003E\n\t \u003Ctd\u003E\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u003C\/td\u003E\n\t\u003C\/tr\u003E\n\u003C\/table\u003E"}],"label":"\u003Ctable\u003E\n\t\u003Ctr\u003E\n\t \u003Ctd\u003E2.2\u003C\/td\u003E\n\t \u003Ctd\u003E\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u003C\/td\u003E\n\t\u003C\/tr\u003E\n\u003C\/table\u003E"},{"id":7,"number":"2.3","name":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","parent_id":"2","label":"\u003Ctable\u003E\n\t\u003Ctr\u003E\n\t \u003Ctd\u003E2.3\u003C\/td\u003E\n\t \u003Ctd\u003E\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u003C\/td\u003E\n\t\u003C\/tr\u003E\n\u003C\/table\u003E"}],"label":"\u003Ctable\u003E\n\t\u003Ctr\u003E\n\t \u003Ctd\u003E2\u003C\/td\u003E\n\t \u003Ctd\u003E\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u003C\/td\u003E\n\t\u003C\/tr\u003E\n\u003C\/table\u003E"},{"id":8,"number":"3","name":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","parent_id":"0","label":"\u003Ctable\u003E\n\t\u003Ctr\u003E\n\t \u003Ctd\u003E3\u003C\/td\u003E\n\t \u003Ctd\u003E\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u003C\/td\u003E\n\t \u003Ctd\u003E\u003C\/td\u003E\n\t\u003C\/tr\u003E\n\u003C\/table\u003E"}]


Заголовки ответа:
Connection: Keep-Alive
Content-Length: 4031
Content-Type: text/html; charset=UTF-8
Date: Sat, 06 Feb 2016 12:31:06 GMT
Keep-Alive: timeout=5, max=96
Server: Apache/2.4.17 (Win32) OpenSSL/1.0.2d PHP/5.6.14

HTML код в label

Qwentor ★★★★★
() автор топика
Последнее исправление: Qwentor (всего исправлений: 1)

Твиг умеет рав фильтр:

{{ htmlTags | raw }}
Иначе будешь видеть < > а не теги.

Заголовок то какого хрена у тебя text/html? Должно быть application/json.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Твиг не при чем скорее всего. Переменные подставляю текстовые.

<table>
	<tr>
	    <td>{{ number }}</td>
	    <td>{{ name }}</td>
	    <td>{{ description }}</td>
	    <td></td>
	</tr>
</table>


Потом сохраняю все в переменную

Qwentor ★★★★★
() автор топика
Ответ на: комментарий от Qwentor

Все окей, парсится в нужную структуру:

[
    {
        description: "Описание",
        id: 1,
        label: "<table>
	    <tr>
	        <td>1</td>
	        <td>Название</td>
	        <td>Описание</td>
	        <td></td>
	     </tr>
        </table>", 
        name: "Название",
        number: "1",
        parent_id: "0"
    },
    ...
]
А теперь, я иду на офф. документацию JqTree (ты же этот плагин имеешь ввиду?)
http://mbraak.github.io/jqTree/
И вижу, тут же, в демо:
{
    label: 'node1', id: 1,
    children: [
        { label: 'child1', id: 2 },
        { label: 'child2', id: 3 }
    ]
},
Там же, рядом, справа - отображается результат, то есть label, это просто какое-то наименование, а ты туда пихаешь целую html-таблицу. Ты этот плагин имел ввиду? Или какой-то другой?

znenyegvkby
()
Ответ на: комментарий от deep-purple

Ну не было пока времени убунту на новый ноут накатить) Как только так сразу)

Qwentor ★★★★★
() автор топика
Ответ на: комментарий от znenyegvkby

Да, этот. Может из-за этого и не выходит ничего. Какой посоветуете тогда другой, чтоб точно все работало?

Qwentor ★★★★★
() автор топика
Ответ на: комментарий от Qwentor

Что должно работать-то? Это ведь просто плагин состовления древовидной структуры, из обычного JSON. То есть, label, это просто ярлычек, и из вашей структуры должно было выйти, что-то наподобии:

    node1(it_is_label)
        child1(it_is_label)
        child2(it_is_label)
    node2(is_is_label)
    ...
А вы, в is_is_label, хотите чтобы была таблица с заголовком? Я совсем не понимаю, что вы хотите получить в итоге. Если расскажите, то я посоветую дельный плагин.
Я не качал этот плагин, и не был в коде, я думаю что в label вставляются данные «как есть», то есть html код экранируется и отображается просто со всеми символами, то есть вы можете найти это внутри плагина, и изменить на нужный вам результат, но я даже не могу предположить зачем вам это? Какого конечного результата вы добиваетесь?

znenyegvkby
()
Ответ на: комментарий от znenyegvkby

Конечный результат:
вместо строчки-названия должна быть таблица, слева от нее +/- для открытия подтаблицы и т.д. Т.е. должен быть не маленький заголовок, а содержимое. Возможно, это будет выглядеть кривовато, но так нужно. Спасибо за то, что со мной возились)) А за плагин был бы безмерно благодарен

Qwentor ★★★★★
() автор топика
Ответ на: комментарий от Qwentor

Ну или можно почитать документацию. Вот что я там нашел. http://mbraak.github.io/jqTree/examples/06_autoescape.html То есть, если выставить

autoEscape: false
То символы не будут экранироваться. Скачал плагин, проверил. Все окей, только таблица отображается криво, ибо у них идет вставка через метод в коде (строка 1623, если ничего там не меняли)
NodeElement.prototype.getSpan = function() {
    return this.$element.children('.jqtree-element').find('span.jqtree-title');
  };
Поэтому ваша таблица все равно попадет в span. Что вам не подходит, поэтому придется изменить код плагина. Дописывайте новую функцию NodeELement.prototype.getDiv, и меняйте везде в коде на getSpan, если установлен какая-либо опция. Придумайте любую свою опцию (label_is_html), допустим. Ну или вы можете тупо изменить getSpan, если вам до фени на код, в-принципе там у них все равно не айс код :)

znenyegvkby
()
Ответ на: комментарий от Qwentor

Нет, извиняюсь, поторопился, элемент создается в функции createTitleSpan (строка 650)

ElementsRenderer.prototype.createTitleSpan = function(node_name, level, is_selected, is_open, is_folder) {
    var classes, title_span;
    title_span = document.createElement('span');
    classes = "jqtree-title jqtree_common";
    if (is_folder) {
      classes += " jqtree-title-folder";
    }
    title_span.className = classes;
    title_span.setAttribute('role', 'treeitem');
    title_span.setAttribute('aria-level', level);
    title_span.setAttribute('aria-selected', util.getBoolString(is_selected));
    title_span.setAttribute('aria-expanded', util.getBoolString(is_open));
    if (is_selected) {
      title_span.setAttribute('tabindex', 0);
    }
    title_span.innerHTML = this.escapeIfNecessary(node_name);
    return title_span;
};
Меняйте здесь, лучше добавьте еще один параметр, как в функцию (is_html_label), и если true, то создавайте title через div, а еще лучше напишите метод createTitleDiv, чтобы не от отставать от библиотеки. Только не забудьте потом изменить нужные вам стили в jqtree.css

znenyegvkby
()
Ответ на: комментарий от znenyegvkby

таблица отображается криво

В чем у вас проявляется?
У меня рамка только вокруг внешних границ делается, хотя

table.node{border: 1px solid black;}

Qwentor ★★★★★
() автор топика
Ответ на: комментарий от Qwentor

Да ни в чем, в принципе, просто таблица без стилей. Но у них span не отображается как блоковой элемент, он у них стандартный, то есть inline, и вставлять в него таблицы как это по определению не комильфо. Особенно, если будете как-нить по особому ее оформлять. Поэтому я и сказал что лучше сделать отдельный метод createTitleDiv, который будет вам возвращать node обернутый в div, что будет более каноничным с точки зрения html. Но тут уж как говорится, на вкус и цвет...

znenyegvkby
()
Ответ на: комментарий от znenyegvkby

Спасибо! Пока сделал как по-быстрому, позже переделаю на правильно

Qwentor ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.