1

我有一个关于 ajax 小部件的真正菜鸟问题。这真的是我刚才问的一个问题的延伸:金字塔和变色龙中的 ajax 小部件

如果您查看这个问题和文件 account_login_widget.pt 的内容,您会看到“widget”使用类似 ${username} 的语法。这再次适用于页面上只有一个登录小部件,但是尝试将这种“小部件模式”用于可以在页面上多次存在的小部件时,一切都会变得松散。

现在我想创建一个 ajax 切换按钮。按钮应该是可配置的:按钮的文本可以根据它使用的页面而改变,并且回调代码也应该能够改变......再次取决于页面。此外,多个切换按钮应该能够存在于同一页面上。

2个问题:

  1. 假设我的页面上有一个餐厅列表,每个餐厅旁边都有一个“喜欢”按钮。将餐厅 ID 传递给“发布”服务器调用的正确方法是什么(即:如何将变量传递给 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>

谢谢!

4

1 回答 1

1

我觉得你只是为了一个like按钮做太多的工作,我讨厌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”来标识每个按钮,后缀为我以 base36 形式发送/接收的帖子 ID,并用下划线分隔这两个名称。然后我使用 javascript 从每个按钮的 ID 中提取帖子的 ID。

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

我的退订功能基本相同。请注意我是如何从按钮的 ID 属性接收帖子 ID 的。/api/subscribe/ 和 /api/unsubscribe/ 路由只接受一个参数 id,并让 request.user 订阅具有该 id 的帖子。如果 request.user 或 _csrf 不存在,这些路由将不起作用。

我的版本要短得多,并且可以肯定地工作。希望这对您有所帮助。

对于喜欢和关注,我会编写两个模板和两组 javascript 函数,假设它们使用完全不同的控制器。如果您尝试复制 Facebook,其中 Like、Subscribe 和 Follow 都是一样的,那么您需要做的就是让模板允许不同的文本:

<%def name="subscribe(post, subtitle='subscribe', unsubtitle='unsubscribe')">
...
<span ...>${subtitle}</span>
<span ...>${unsubtitle}</span>
</%def>
于 2011-12-28T02:25:42.933 回答