模板语言和 ajax 小部件
我有一个关于 ajax 小部件的菜鸟问题。这实际上是我不久前问过的一个问题的扩展:金字塔和变色龙中的ajax小部件< /a>
如果您查看此问题和文件 account_login_widget.pt 的内容,您将看到“小部件”使用类似 ${username} 的语法。这对于页面上只有一个的登录小部件再次有效,但是尝试将这种“小部件模式”用于可以在页面上多次存在的小部件,一切都会变得混乱。
现在我想创建一个 ajax 切换按钮。按钮应该是可配置的:按钮的文本可以根据它所使用的页面而改变,并且回调代码也应该能够改变......再次取决于页面。此外,同一页面上应该能够存在多个切换按钮。
2 个问题:
假设我的页面上有一个餐厅列表,每个餐厅旁边都有一个“赞”按钮。将餐厅 ID 传递给“post”服务器调用的正确方法是什么(即:如何将变量传递给 javascript 小部件?)。
在同一页面上,假设我想使用相同的 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>
谢谢!
I have a really noob question about ajax widgets. It's really an extension of a question I asked a while ago: ajax widgets in pyramid and chameleon
If you look at this question and the contents of the file account_login_widget.pt, you'll see the 'widget' uses syntax like ${username}. This works again for a login widget of which there is only ever one on a page, but all hell breaks loose trying to use this 'widget pattern' for widgets that can exist multiple times on a page.
Now I want to create an ajax toggle button. The button should be configurable: the text of the button can change depending on the page it's used on, and the callback code should be able to be changed too...again depending on the page. Additionally multiple toggle buttons should be able to exist on the same page.
2 questions:
Let's say I have a list of restaurants on my page and a 'Like' button next to each. What is the correct way to pass the restaurant id to the 'post' server call (ie: how do you pass variables to the javascript widget?).
On the same page, let's say I want to use the same ajax toggle button widget, but in a different context. Let's say, on the same page I also have a list of people and I want to 'Follow' them. What's the correct way to pass the button text variable into the widget and also change the post server call behavior? (ie: In question 1 maybe I want to call restaurant.like(), but in question 2 I want to call person.follow()
Here is some sample code showing the widget...
<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>
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我觉得你只是为了一个喜欢的按钮做了太多的工作,而且我讨厌 JavaScript,所以我尽量避免它,特别是在文档加载方面,因为它滞后于用户的浏览器。我将发布我用于“订阅”的内容,希望它能以某种方式帮助您。
在控制器中,我有一个创建订阅按钮的模板。我没有更改单个按钮的名称,而是制作了两个按钮,其中一个隐藏(或禁用)。这实际上不应该比您当前所做的花费更多的时间。使用Mako(不熟悉Chameleon),模板功能是:
当前用户对象存储在request.user中,subscribe是一个布尔值,告诉我当前用户是否订阅了当前的“post”。我使用按钮名称“sub”或“unsub”来标识每个按钮,后缀为我以 Base36 形式发送/接收的帖子 ID,并用下划线分隔这两个名称。然后,我使用 javascript 从每个按钮的 ID 中提取帖子的 ID。
我的取消订阅功能基本相同。请注意我如何从按钮的 ID 属性接收帖子的 ID。 /api/subscribe/ 和 /api/unsubscribe/ 路由仅采用一个参数 id,并使 request.user 使用该 id 订阅帖子。如果 request.user 或 _csrf 不存在,这些路由将不起作用。
我的版本要短得多并且肯定有效。希望这对您有帮助。
对于喜欢和跟随,我会编写两个模板和两组 JavaScript 函数,假设它们使用完全不同的控制器。如果您尝试复制 Facebook,其中“点赞”、“订阅”和“关注”都是同一件事,那么您所需要做的就是让模板允许不同的文本:
I feel like you're doing way too much work just for a like button and I hate javascript so I try to avoid it as much as possible, especially on document loads since it lags the user's browser. I'm going to post what I use for "subscriptions", and hopefully it helps you in some way.
In the controller, I have a template that creates a subscription button. Instead of changing names on a single button, I make two buttons with one hidden (or disabled). This really shouldn't take much more time than what you currently do. Using Mako (not familiar with Chameleon), the template function is:
The current user object is stored in request.user, and subscribe is a boolean telling me whether the current user is subscribed to the current "post". I ID each button with a button name, "sub" or "unsub", postfixed with the ID of the post, which I send/receive in base36 form, and separate these two names with an underscore. I then use javascript to extract the ID of the post out of each button's ID.
I have basically the same function for unsubscribing. Notice how I receive the post's ID from the button's ID attribute. The /api/subscribe/ and /api/unsubscribe/ route takes only one parameter, id, and makes request.user subscribe to the post with that id. These routes won't work if request.user or _csrf doesn't exist.
My version is much shorter and works for sure. Hopefully this helps you.
For likes vs follows, I would write two templates and two sets of javascript functions, assuming they use entirely different controllers. If you're trying to copy Facebook where Like, Subscribe, and Follow are all the same thing, then all you need to do is have the template allow different texts: