Как связать данные на стороне сервера с клиентскими элементами пользовательского интерфейса в HTML?

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

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

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

Ответ 1

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

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

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

Настройка "id =" comment-123 ", тогда сканирование всех строк с идентификатором, начинающимся с" comment ", действительно полезно для вашего конкретного случая. Для установки неидентифицирующих дополнительных атрибутов информации вы можете использовать либо атрибуты данных HTML5, либо взломать их в имя класса, используя, например." class= "комментарий типа-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 Level 3 LS должны содержать их по умолчанию, и все браузеры и основная библиотека XML до сих пор делают.

Ответ 2

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
});

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

Ответ 3

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

  • При рендеринге страницы на стороне сервера создайте ссылку флага как нормальную ссылку, чтобы она работала нормально, если у вас не было включен 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>

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