页面装载中...

使用 jQuery 实现 Ajax 留言

写点废话当作前言

今天花了点时间在自己的 blog 上实现了非插件式的 Ajax 留言功能,当然,还是基于我们很好很强大的 jQuery 框架。基本思路就是利用 jQuery 的 Ajax API 把留言数据提交给 comments-ajax.php 完成留言,我们分三步实现,第一步要先改造 comments.php,第二步实现 jQuery 代码,第三步编写一个 comments-ajax.php 用来接收留言数据并完成对 WP 数据库的操作。

改造 comments.php

这一步不是必须的,你完全可以写一份适用于非标准的 comments.php 的 jQuery 代码,不过还是建议你把留言模板中的各个元素的 ID 定义标准,譬如把填写留言信息的表单(form)的 ID 设为 #commentform,留言 列表 ul 或 ol 的 ID 设为 #commentlist 等等。另外,视具体情况,你可能需要在合适的地方新增两个 span 元素,ID 分别设为 #commentload 和 #commenterror,用来显示留言提交状态和错误信息,不过这也不是必须的。然后,把整个 #commentform 和附属的元素用一个大的 div 包进来,ID 设为 #commentformbox,…… 你猜对了,这一步仍然不是必须的,我们做这么多不过是为了迎合下面的 jQuery 脚本,我在这里贴出来的可能只直接适用于自己的主题,但是如果你能够看得懂下面的代码,那么你也明白怎么样把这些代码改为适合自己的。 :lol:

实现相应的 jQuery 代码:comments.js

jQuery 提供了 jQuery.ajax API,使用起来相当简便,在这里,我们需要用到的参数有 String url, Object data, String type, Function beforeSend, Function error, Function success,前三个参数用来定义 Ajax 请求的地址、数据、请求类型,后三个函数用来给发送请求之前、发生错误和请求成功添加处理动作。

以下是代码(借鉴于同样很好很强大的 K2 主题,并做了部分修改):

if ($('#commentform').length) {
    $('#commentform').submit(function(){
        jQuery.ajax({
            url: 'comments-ajax.php', // 这里要改为 comments-ajax.php 文件的位置
            data: $('#commentform').serialize(), // 从表单中获取数据
            type: 'POST', // 设置请求类型为 ‘POST’,默认为 ‘GET’
            beforeSend: function() {
                $('#commenterror').hide();
                $('#commentload').show();
            },
            error: function(request) {
                $('#commentload').hide();
                $('#commenterror').show().html(request.responseText);
            },
            success: function(data) {
                $('textarea').each(function(){
                    this.value='';
                });
                $('#commenterror').hide().html();
                $('#comments').html(parseInt($('#comments').html()) + 1);
                if (!$('#commentlist').length) {
                    $('#pinglist').before('<ul id="commentlist"></ul>');
                }
                $('#commentlist').append(data); // 追加留言数据
                $('#commentform :input').attr('disabled', true);
                $('#commentformbox').fadeOut(1000);
                $('#commentload').hide();
                setTimeout(function() { // 提交留言 15 秒后方可再次提交新留言
                    $('#commentform :input').removeAttr('disabled');
                    $('#commentformbox').fadeIn(1000);
                }, 15000);
            }
        });
        return false;
    });
}

编写 comments-ajax.php

这个文件就是我们刚才写好的 jQuery 代码请求的链接,用来把从 #commentform 表单中得到的信息添加至 WP 数据库中。下面这段代码是直接从 K2 主题中 COPY 过来的(感谢 K2 的数位作者!),需要注意的是,最后一部分的 li 元素(对应于一条留言)需要修改到与你自己的 comments.php 相适应:

<?php
if ($_SERVER["REQUEST_METHOD"] != "POST") {
    header('Allow: POST');
    header("HTTP/1.1 405 Method Not Allowed");
    header("Content-type: text/plain");
    exit;
}
$db_check = true;
function kill_data() {
    return '';
}
function check_db() {
    global $wpdb, $db_check;
    if($db_check) {
        // Check DB
        if(!$wpdb->dbh) {
            echo('Our database has issues. Try again later.');
        } else {
            echo('We\'re currently having site problems. Try again later.');
        }
        die();
    }
}
ob_start('kill_data');
register_shutdown_function('check_db');
require_once(dirname(__FILE__)."/../../../wp-config.php");
$db_check = false;
ob_end_clean();
nocache_headers();
function fail($s) {
    header('HTTP/1.0 500 Internal Server Error');
    echo $s;
    exit;
}
$comment_post_ID = (int) $_POST['comment_post_ID'];
$status = $wpdb->get_row("SELECT post_status, comment_status FROM $wpdb->posts WHERE ID = '$comment_post_ID'");
if ( empty($status->comment_status) ) {
    do_action('comment_id_not_found', $comment_post_ID);
    fail('The post you are trying to comment on does not currently exist in the database.');
} elseif ( 'closed' ==  $status->comment_status ) {
    do_action('comment_closed', $comment_post_ID);
    fail('Sorry, comments are closed for this item.');
} elseif ( in_array($status->post_status, array('draft', 'pending') ) ) {
    do_action('comment_on_draft', $comment_post_ID);
    fail('The post you are trying to comment on has not been published.');
}
$comment_author       = trim(strip_tags($_POST['author']));
$comment_author_email = trim($_POST['email']);
$comment_author_url   = trim($_POST['url']);
$comment_content      = trim($_POST['comment']);
// If the user is logged in
$user = wp_get_current_user();
if ( $user->ID ) {
    $comment_author       = $wpdb->escape($user->display_name);
    $comment_author_email = $wpdb->escape($user->user_email);
    $comment_author_url   = $wpdb->escape($user->user_url);
    if ( current_user_can('unfiltered_html') ) {
        if ( wp_create_nonce('unfiltered-html-comment_' . $comment_post_ID) != $_POST['_wp_unfiltered_html_comment'] ) {
            kses_remove_filters(); // start with a clean slate
            kses_init_filters(); // set up the filters
        }
    }
} else {
    if ( get_option('comment_registration') )
        fail('Sorry, you must be logged in to post a comment.');
}
$comment_type = '';
if ( get_option('require_name_email') && !$user->ID ) {
    if ( 6> strlen($comment_author_email) || '' == $comment_author )
        fail('Error: please fill the required fields (name, email).');
    elseif ( !is_email($comment_author_email))
        fail('Error: please enter a valid email address.');
}
if ( '' == $comment_content )
    fail('Error: please type a comment.');
// Simple duplicate check
$dupe = "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = '$comment_post_ID' AND ( comment_author = '$comment_author' ";
if ( $comment_author_email ) $dupe .= "OR comment_author_email = '$comment_author_email' ";
$dupe .= ") AND comment_content = '$comment_content' LIMIT 1";
if ( $wpdb->get_var($dupe) ) {
    fail('Duplicate comment detected; it looks as though you\'ve already said that!');
}
$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'user_ID');
$comment_id = wp_new_comment( $commentdata );
$comment = get_comment($comment_id);
if ( !$user->ID ) {
    setcookie('comment_author_' . COOKIEHASH, $comment->comment_author, time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
    setcookie('comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
    setcookie('comment_author_url_' . COOKIEHASH, clean_url($comment->comment_author_url), time() + 30000000, COOKIEPATH, COOKIE_DOMAIN);
}
@header('Content-type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset'));
$comment->comment_type = 'comment';
$comment_index = $_POST['comment_count'] + 1;
?>
<li id="comment-<?php echo $comment->comment_ID; ?>">
<!-- 这里需要添加你的代码 -->
</li>

收尾工作及测试

上面的工作做完后,把这几个文件存在当前主题所在目录下面,记得在 header.php 中引入 jQuery 框架和你刚才写好的 comments.js,否则留言功能是不起作用的哦。在浏览器中按下 Ctrl + F5 重新加载你的 blog 日志后,写几句话提交,是不是已经变成 Ajax 的了?留言提交成功后,留言框 #commentformbox “淡出”的效果看到了么,过 15 秒后它又会“淡入”。嗯,对了,你也发现了,在点击提交留言的按钮之后,如果没有一个不断旋转的动画图标 submitting... 表达“正在提交”,肯定不够过瘾,那我们来把它加上,把这个图标另存到你的主题所在目录下的 images 目录下(绕口令),然后打开 style.css 在其中加上一句:

#commentload {
display: none;
height: 18px;
width: 18px;
background: url('images/spinner.gif') no-repeat center center;
}

当然,如果觉得这个动画图标不好看,你可以到这里生成你最中意的。

结束语

行了,就写这么多吧,漏了什么等发现了再补。我的感受:偶尔尝试一下不靠插件自己动手实现自己想要的功能,其实也蛮过瘾!动手之前想试试效果吗?给我留个言试试吧 :lol:

你可能会有兴趣继续阅读

82排都被占了... 抢座 或 Trackback

  • AndyWxy 2007年11月13日 21:59 

    那我先来试试,趁漫步他还没来。。。晕,今天被他说是沙发党了,hoho~ 这年头好东西太多,不当也难那~ 哇哈。。。看看效果~~

  • AndyWxy 2007年11月13日 22:04 

    效果挺赞! 这个一定要试试哈哈! 要关注细节啊!

  • 漫步 2007年11月13日 22:11 

    我倒,我竟然没抢到沙发…我也来试一下.

  • 李晨英语 2007年11月14日 03:51 

    冰仔,不出几个月,你肯定能做出风靡WP界的一流主题 ^_^

  • 北极冰仔 2007年11月14日 08:55 

    AndyWxy & 漫步 » 哈哈,欢迎沙发党光临!

    Steven » 哪里哪里,我的水平比起 yichi 或 Nick La 他们差好几个数量级,他们才是真正的大牛。

  • 传奇世界私服 2007年11月14日 10:25 

    冷板板也是不错的,先冒个小小泡,来试下

  • Cloudream 2007年11月14日 10:53 

    测试一下效果……(逃

  • 十哈 2007年11月14日 11:51 

    试试效果。

  • 漫步 2007年11月14日 12:56 

    快帮我做主题。。。。

  • 北极冰仔 2007年11月14日 13:08 

    漫步 » 感觉没什么灵感哇……真羡慕那些大师级人物

  • 漫步 2007年11月14日 19:05 

    我不急,我可以降低要求,你做个demo出来了,

  • sansky 2007年11月14日 19:51 

    高人,
    我现在改主题的布局都费劲。

  • cosbeta 2007年11月14日 22:59 

    sansky :慢慢改吧,哈哈!

  • 北极冰仔 2007年11月15日 18:24 

    这是一条用来测试的留言。

  • felix 2007年11月15日 19:09 

    o(∩_∩)o…

  • MO 2007年11月16日 14:18 

    先测试下效果,然后慢慢学习慢慢啃^-^

  • MO 2007年11月16日 15:12 

    -_-!改不出来效果,看来得慢慢研究了

  • 小胖 2007年11月16日 15:41 

    我也test

  • caca 2007年11月23日 14:27 

    bu cuo a

  • 北极冰仔 2007年11月25日 11:33 

    更改样式后的新测试。

  • infoseek 2007年11月27日 14:42 

    试试

  • 北极冰仔 2007年12月06日 11:46 

    改了点东西,再测试测试。

  • fdf 2007年12月07日 16:12 

    测试测试。

  • Chris 2007年12月12日 00:14 

    看看效果先~

  • 我来看看 2007年12月17日 21:33 

    看看怎样

  • AndyWxy 2007年12月29日 15:44 

    哦~ 冰仔又改主题了,看看现在的效果是怎样滴,嘿嘿~:-?

  • 北极冰仔 2007年12月30日 12:53 

    更改路径测试

  • hypcloud 2007年12月30日 14:50 

    不错

  • SkyLanD 2007年12月30日 20:26 

    请问一下,首页显示最新留言的插件是什么?谢谢

    外加 TEST

  • 北极冰仔 2007年12月31日 17:06 

    SkyLand » 留言是用 Brian’s Latest Comments 实现的。欢迎你,SkyLand。

  • Tevez 2008年01月13日 11:42 

    好东西!

  • fly 2008年01月15日 10:17 

  • xhlv 2008年01月15日 15:49 

    不错

  • bhqt 2008年01月16日 09:33 

    我也test

  • nightbaby 2008年01月21日 15:45 

    说实话,看不太懂,不过佩服。

  • Hivan 2008年01月23日 00:29 

    我也留言试试!

    Hivan’s last blog post..妙用wordpress.com.cn

  • Jezzy 2008年01月25日 13:04 

    也试试效果

  • ww 2008年02月12日 00:16 

    测试一下

  • 你好 2008年02月14日 20:41 

    你好,我想用WP建个自己的博客,已经观望了很久了,发现这个模版(http://www.plaintxt.org/themes/sandbox/) Sandbox v1.3 非常不错, 但是惟独没有Ajax 留言功能, 我想在这个模版上添加Ajax 留言功能, 自己按照你这篇文章说的在本地试了N遍了,仍然不行, 希望大哥能帮忙在Sandbox v1.3 这个模版的基础上添加Ajax 留言功能, 十分感谢, 如果做好了请帮忙发邮件至 jlj588#gmail.com 谢谢!

  • andrye 2008年02月15日 23:11 

    测试+学习

  • asiapan 2008年02月18日 11:04 

    各种功能配合起来,真是感觉很棒啊,有技术太让人羡慕了

    asiapan’s last blog post..今日收藏 [2008-02-16]:asiapan @ del.icio.us

  • asiapan 2008年02月18日 11:56 

    你好,请问你的留言部分出现的那个留言者的last blog post是怎么实现的?页面滑动的效果也很棒。

    asiapan’s last blog post..淘书爽、车票烦

  • fdfdfd 2008年02月19日 20:53 

    fdfd

  • fdfdfd 2008年02月19日 20:53 

    fdfdf

  • 头天 2008年02月19日 23:39 

    地方

  • TT 2008年02月20日 00:17 

    还有细节没考虑啊 留言统计也不够精确啊 呵呵

  • TT 2008年02月20日 00:20 

    淡入 测试

  • Hivan 2008年02月28日 14:09 

    云里雾里..

    Hivan’s last blog post..FON WIFI全面覆盖东京

  • asdf 2008年03月03日 16:35 

    ssdfs

  • asdf 2008年03月03日 16:36 

    sdf

  • Neil 2008年03月04日 23:15 

    我也测试一下,学习后折腾一下自己的theme

  • Neil 2008年03月05日 00:28 

    测试一下淡入效果~~~

  • asdf 2008年03月05日 10:27 

    Test~

  • neveta 2008年03月09日 23:49 

    test

  • 测试 2008年03月11日 13:16 

    wo ceshi meiyong

  • 测试 2008年03月11日 13:16 

    yuanlaizheyanga

  • hello 2008年03月15日 11:17 

    test

  • 赫赫 2008年03月18日 15:07 

    this is a very good example of Jquery use in ajax

  • asing 2008年03月20日 17:52 

    just test

    asing’s last blog post..google有特色

  • 北极冰仔 2008年03月23日 19:12 

    重新测试一下。

  • xzczxcz 2008年03月29日 00:53 

    xczczxcxzcxz

  • Gu 2008年03月29日 11:41 

    jQuery is good

  • sam 2008年03月31日 11:09 

    dsafdsfsdf

  • test 2008年04月04日 22:25 

    test

  • Shawn 2008年04月05日 11:12 

    我太懒了,不过这个是一定要看的。

  • test 2008年04月07日 21:29 

    dddddddddddddddddddddddddddddddddd

  • test 2008年04月07日 21:50 

    再测试多一次

  • test 2008年04月07日 23:02 

    猛击提交……囧

  • test 2008年04月11日 15:21 

    我也来测试一次

  • tes 2008年04月20日 01:37 

    sss

  • CallMeGod 2008年04月28日 12:25 

    赞!

  • CallMeGod 2008年04月28日 12:26 

    不错

  • isee 2008年05月01日 14:39 

    试试

  • Munez 2008年05月02日 11:53 

    good

  • Munez 2008年05月02日 11:53 

    SDF

  • 追风逐月 2008年05月04日 01:15 

    占个位置,挺喜欢jquery的,回头也弄个这样的留言去

  • lphy 2008年05月06日 21:27 

    嘿嘿,测试一下效果,看看可以的话改到我的GAE留言板上面去:)

  • purose.cn 2008年05月07日 12:34 

    我来测试一下,呵呵……

  • ddd 2008年05月07日 13:41 

    eeeee

  • 打碎打碎大 2008年05月08日 11:17 

    非法所得

  • ddd 2008年05月09日 16:52 

    1111

  • ddd 2008年05月09日 16:53 

    1

我要占座!

Connecting to server...