языки шаблонов и виджеты ajax

У меня действительно нубский вопрос о виджетах ajax. Это действительно расширение вопроса, который я задал некоторое время назад: виджеты ajax в пирамиде и хамелеоне< /а>

Если вы посмотрите на этот вопрос и содержимое файла account_login_widget.pt, вы увидите, что «виджет» использует такой синтаксис, как ${username}. Это снова работает для виджета входа в систему, который всегда есть только один на странице, но все рушится, пытаясь использовать этот «шаблон виджета» для виджетов, которые могут существовать несколько раз на странице.

Теперь я хочу создать кнопку переключения ajax. Кнопка должна быть настраиваемой: текст кнопки может меняться в зависимости от страницы, на которой она используется, и код обратного вызова тоже должен быть изменен... опять же в зависимости от страницы. Кроме того, на одной странице должно быть несколько кнопок-переключателей.

2 вопроса:

  1. Допустим, у меня есть список ресторанов на моей странице и кнопка «Нравится» рядом с каждым. Каков правильный способ передачи идентификатора ресторана на вызов почтового сервера (например: как вы передаете переменные в виджет javascript?).

  2. Допустим, на той же странице я хочу использовать тот же виджет кнопки переключения ajax, но в другом контексте. Скажем, на той же странице у меня также есть список людей, и я хочу «подписаться» на них. Как правильно передать текстовую переменную кнопки в виджет, а также изменить поведение вызова почтового сервера? (то есть: в вопросе 1, возможно, я хочу вызвать restaurant.like(), но в вопросе 2 я хочу вызвать person.follow()

Вот пример кода, показывающий виджет...

<script type="text/javascript">
// plugin implementation
(function($) {
$.fn.create_ajax_toggle_button = function(csrf, name, toggle_on, url, on_text, off_text) {
    return this.each(function() {
        var anchor = $('<a></a>');
        anchor.appendTo(this);

        $(anchor).button();

        $(anchor).toggle_ajax_button_text(toggle_on, on_text, off_text);

        $(anchor).click(function(e) {
            var form_data = '_csrf=' + csrf + '&name=' + name + '&toggle_on=' + toggle_on;

            $.post(url, form_data, function(response) {
                $.fn.toggle_ajax_button_text();
            });
        });
    });
};

$.fn.toggle_ajax_button_text = function(toggle_on, on_text, off_text) {
    if (toggle_on == 'True') {
        $(this).toggleClass('ui-state-active');
        $(this).text(on_text);          
    } else {
        $(this).text(off_text);             
    }
};
})(jQuery);

// Define the entry point    
$(document).ready(function() {
    // YUCK!!! I really shouldn't be/can't using ${name} templating
    // syntax like this.  Doing this means the JS code needs to be
    // loaded over and over again for each item in the list.  This
    // just doesn't work.  :-(
    $('.ajax_toggle_button_div_${name}').create_ajax_toggle_button('${csrf}', '${name}',     '${toggle_on}', '${url}', '${on_text}', '${off_text}');
});
</script>

<div class="ajax_toggle_button_div_${name}"></div>

Спасибо!


person lostdorje    schedule 27.12.2011    source источник


Ответы (1)


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

В контроллере у меня есть шаблон, который создает кнопку подписки. Вместо того, чтобы менять имена на одной кнопке, я делаю две кнопки, одна из которых скрыта (или отключена). На самом деле это не должно занимать намного больше времени, чем то, что вы делаете сейчас. Используя Mako (не знакомый с Chameleon), функция шаблона:

<%def name="subscribe(post)">
% if request.user:
<% subscribe = Bookmark_C.check_subscribed(request.user.id, post.id) %>
<span class="pstnm">${Bookmark_C.get_num_subscribers(post.id)}</span>
<span class="pstbtn${' hide' if subscribe else ''}" id="sub_${post.base36}" onclick="subscribe(this)">subscribe</span>
<span class="pstbtn${' hide' if not subscribe else ''}" id="unsub_${post.base36}" onclick="unsubscribe(this)">unsubscribe</span>
% endif
</%def>

Текущий пользовательский объект хранится в request.user, а subscribe — это логическое значение, сообщающее мне, подписан ли текущий пользователь на текущую «публикацию». Я идентифицирую каждую кнопку именем кнопки, "sub" или "unsub", с постфиксом ID поста, который я отправляю/получаю в форме base36, и разделяю эти два имени символом подчеркивания. Затем я использую javascript для извлечения идентификатора сообщения из идентификатора каждой кнопки.

function subscribe(obj) {
  var id = $(obj).attr("id").split('_')[1];
  $.post(
    "/api/subscribe/",
    {id: id, _csrf: _csrf},
    function () {
      $('#sub_' + id).hide();
      $('#unsub_' + id).show();
    }
  );
}

У меня в принципе такая же функция для отписки. Обратите внимание, как я получаю идентификатор сообщения из атрибута идентификатора кнопки. Маршрут /api/subscribe/ и /api/unsubscribe/ принимает только один параметр, идентификатор, и заставляет request.user подписаться на сообщение с этим идентификатором. Эти маршруты не будут работать, если request.user или _csrf не существует.

Моя версия намного короче и точно работает. Надеюсь, это поможет вам.

Для лайков и подписок я бы написал два шаблона и два набора функций javascript, предполагая, что они используют совершенно разные контроллеры. Если вы пытаетесь скопировать Facebook, где «Нравится», «Подписаться» и «Подписаться» — это одно и то же, то все, что вам нужно сделать, — это разрешить в шаблоне разные тексты:

<%def name="subscribe(post, subtitle='subscribe', unsubtitle='unsubscribe')">
...
<span ...>${subtitle}</span>
<span ...>${unsubtitle}</span>
</%def>
person Jonathan Ong    schedule 28.12.2011
comment
Спасибо за подробный ответ. Это немного менее общее, чем то, чего я пытаюсь достичь, но в конечном итоге я могу просто пойти по этому пути. - person lostdorje; 02.01.2012