Как связать данные на стороне сервера с элементами пользовательского интерфейса на стороне клиента в HTML? - PullRequest
2 голосов
/ 26 августа 2009

Я постоянно сталкиваюсь с этой проблемой при разработке приложений AJAX. Допустим, я хочу, чтобы пользователи могли нажимать на значок «флаг», связанный с каждым комментарием на моем сайте, что приводит к отправке AJAX-запроса на сервер с просьбой пометить комментарий. Мне нужно связать идентификатор комментария с комментарием на стороне клиента, чтобы запрос AJAX мог сообщить серверу, какой комментарий пометить.

На этой странице объясняется несколько способов аннотирования HTML таким образом, но ни один из них не является удовлетворительным. Хотя я мог бы просто использовать идентификатор или атрибут класса, чтобы связать идентификатор комментария с кнопкой флага (например, id = "comment_1998221"), это не удается с более сложными данными, которые не вписываются в эти атрибуты (например, произвольные строки). Есть ли лучшая практика для такого рода вещей? Каждый раз, когда мне нужно сделать это, я получаю некоторый клудж, такой как использование атрибута id, скрытое поле формы или, что еще хуже, диапазон отображения, отображаемый: none.

Атрибуты HTML5 data- * кажутся идеальным решением, но я видел много враждебности к ним, что заставляет меня думать, что у людей уже должно быть решение, которым они довольны. Я хотел бы знать, что это такое.

Ответы [ 3 ]

2 голосов
/ 26 августа 2009

На этой странице объясняется несколько способов аннотирования HTML таким способом, но ни один из них не является удовлетворительным.

Тем не менее, они в значительной степени все, что у вас есть. Хотя эта страница не очень хорошая сводка, есть ошибки, и она неправильно понимает, что означает «ненавязчивый» JavaScript.

Например, на самом деле совершенно правильно помещать элемент script внутри тела, но не непосредственно внутри элемента таблицы. Вы можете поместить все фрагменты скрипта внизу таблицы или поместить каждую строку в свою собственную таблицу, или даже с некоторыми ограничениями, если вы собираетесь изменять DOM, внутри рассматриваемой строки.

Установка «id =« comment-123 »», а затем сканирование всех строк с идентификатором, начинающимся с «comment-», действительно подходит для вашего конкретного случая. Для установки неидентифицирующих дополнительных информационных атрибутов вы можете использовать либо HTML5-атрибуты данных, либо взломать его в имени класса, используя, например,. «Class =" comment type-foo data-bar "». Конечно, и идентификаторы, и имена классов имеют свои ограничения относительно того, какие символы вы можете использовать, но возможно закодировать любую строку до допустимых строк. Например, вы можете использовать пользовательскую кодировку в стиле URL, чтобы скрыть не алфавитно-цифровые символы:

<tr class="greeting-Hello_21_20_E2_98_BA">
    ...
</tr>

function getClassAttr(el, name) {
    var prefix= name+'-';
    var classes= el.className.split(' ');
    for (var i= classes.length; i-->0;) {
        if (classes[i].substring(0, prefix.length)==prefix) {
            var value= classes[i].substring(prefix.length);
            return decodeURIComponent(value.split('_').join('%'));
        }
    }
    return null;
}

var greeting= getClassAttr(tr, 'greeting'); // "Hello! ☺"

Таким способом можно даже хранить сложные нестроковые значения, кодируя их строки JavaScript или JSON, а затем извлекая их с помощью exec (или JSON.parse, где доступно).

Однако, если вы положите туда что-нибудь нетривиальное, это скоро станет грязным. Вот где вы можете предпочесть комментарии. Здесь вы можете поместить что угодно, кроме последовательности '-', которую легко избежать, если она окажется в строке.

<table>
    <tr class="comment">
        <td>...</td>
        <!-- {"id": 123, "user": 456} -->
    </tr>
</table>

function getLastComment(node) {
    var results= [];
    for (var i= node.childNodes.length; i-->0;)
        if (node.childNodes[i]==8)
            return node.childNodes[i];
    return null;
}

var user= getLastComment(tr).user;

Сводка предупреждает, что это не может гарантированно работать, потому что парсеры XML могут отбрасывать комментарии, но тогда парсеры DOM уровня 3 должны сохранять их по умолчанию, и до сих пор это делают все браузеры и основные библиотеки XML.

0 голосов
/ 03 декабря 2009

Вот как бы я это сделал:

  • При рендеринге страницы на стороне сервера создайте ссылку флага как обычную ссылку, чтобы она работала нормально, если у вас не включен JavaScript.

    <a class="flag_link" href="/comment/123/flag/"><img src="flag.gif" /></a>

  • Затем в javascript добавьте событие click, чтобы сделать это с помощью ajax. Я буду использовать jQuery для моего примера, но то же самое не трудно сделать без него.

<script>

$('a.flag_link').click(function() {
  $.get($(this).attr('href'), function() {
    alert('you flagged this comment');
  });
});

</script>

Конечно, вы будете делать что-то более удобное для пользователя, чем предупреждение об успехе.

0 голосов
/ 03 декабря 2009

API данных jQuery хорош для этого.

Предположим, у вас есть следующий DOM ...

<div class="comment">
<a href="#">Flag</a>
Some text
</div>

Затем, предполагая, что вы также загружаете эти элементы с помощью ajax, вы можете сделать

$(".comment").data('someKey', (any javascript value/object));

Затем, после нажатия обработчика клика на флаг, вы можете сделать ...

$(".flagSelector").click(function(ev) {
    var extraData = $(this).closest(".comment").data("someKey");
    // use extraData along with your request
});

Если вы генерируете комментарии на стороне сервера и отправляете их вместе с начальной страницей, вам необходимо выяснить, как инициализировать данные. Одним из способов было бы иметь уникальные идентификаторы для комментариев и при загрузке страницы, все еще загружать пользовательские данные с сервера с помощью Ajax.

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