Typecho实现Ajax评论和全站instantclick适配的曲折之路

尚寂新
尚寂新
2017/10/04 07:40

到国庆了 又是一个作死折腾的季节 一回来我就把畅言用原生评论换掉了 并且撤掉了又拍的CDN(不是嫌弃又拍 计划源站CDN就先不用了 CDN对于折腾党来说很头疼 用又拍静态站缓存图片、css、js吧) 评论那块的CSS不想自己写 于是强扒借鉴了下Typecho原生的评论CSS 加上了一些小功能啊 这些小功能就不再次写出了 下面放链接

这样 评论区里面这几个功能就实现了 随后开始搞评论的Ajax 先是用了情留メ蚊子的AjaxComment 结果发现有一大堆BUG 比如说文章会被重载到评论框中... 然后又用了绛木子的TeComment 这插件在本地环境用的挺好 我还针对我的主题适配改写了这个插件 结果放在实际博客环境中... 诶呦炸了锅了 和评论回复插件有冲突 一评论的时候评论回复的异步页面就开始刷报错... 无奈撤下了这个插件...

评论Ajax加载

Then,我用了泽泽(QQdie)的方案 将下面的代码放进footer附近,然后在上面提前引用好jQuery库

function ajaxc() {
var
   txt_1  = '必须填写用户名',
   txt_2  = '必须填写电子邮箱地址',
   txt_3  = '邮箱地址不合法',
   txt_4  = '必须填写评论内容';
   $body = (window.opera) ? (document.compatMode == "CSS1Compat" ? $('html') : $('body')) : $('html,body');
var
   comments_order = 'DESC',
   comment_list   = '.comment-list',
   comments       = '.comment-num',
   comment_reply  = '.comment-reply',
   comment_form   = '#comment-form',
   respond        = '#comments',
   textarea       = '#textarea',
   submit_btn     = '.submit',
   new_id = '', parent_id = '';

 click_bind();

    $(comment_form).submit(function() { // 提交

        $(submit_btn).attr('disabled', true).fadeTo('slow', 0.5);

       /* 预检 */
        if ($(comment_form).find('#author')[0]) {

            if ($(comment_form).find('#author').val() == '') {
                toastr.info(txt_1);
                msg_effect('#error');
                return false;
            }

            if ($(comment_form).find('#mail').val() == '') {
                toastr.info(txt_2);
                msg_effect('#error');
                return false;
            }

            var filter = /^[^@\s<&>]+@([a-z0-9]+\.)+[a-z]{2,4}$/i;
            if (!filter.test($(comment_form).find('#mail').val())) {
                toastr.info(txt_3);
                msg_effect('#error');
                return false;
            }
        }      
  var textValue = $(comment_form).find(textarea).val().replace(/(^\s*)|(\s*$)/g, "");  //排除空格
        if (textValue == null || textValue == "") {
            toastr.info(txt_4);
            msg_effect('#error');
console.log("内容为空");
            return false;
        }
        $(submit_btn).addClass("active");
       $('#loading').show();
        $.ajax({
            url: $(this).attr('action'),
            type: $(this).attr('method'),
            data: $(this).serializeArray(),
            error: function() {
                toastr.info("提交失败,请重试!");
                msg_effect('#error');
                return false;
            },
            success: function(data) { //成功取到数据
                //console.log(data);
                $(submit_btn).removeClass("active");
               $('#loading').slideUp();
                try {
                    if (!$(comment_list, data).length) {
                        toastr.info("提交失败,可能输入内容不符合规则!");
                        msg_effect('#error');
                        return false;
                    } else {
                        new_id = $(comment_list, data).html().match(/id=\"?comment-\d+/g).join().match(/\d+/g).sort(function(a, b) {
                            return a - b
                        }).pop(); // TODO:找新 id,如果在第二页评论的话,找到的ID是有问题的!

                        if ($('.page-navigator .prev').length && parent_id == ""){
                            new_id = '';
var dd=$(".prev a").attr("href");//获取上页地址
$(".prev a").attr("href",""); //将地址清空
dd=dd.replace(/comment-page-(.*?)#comments/, "comment-page-1#comments");//将获取的地址页码改为1
$(".prev a").attr("href",dd); //将地址放回去
$('.prev a').get(0).click(); //点击这个超链接
                        }//判断当前评论列表是否在第一页,并且只会在母评论时候才会生效

            console.log("new id " + new_id);
                        msg_effect("#success");
                        //插入评论内容到当前页面
                        if (parent_id) {
                            data = $('#li-comment-' + new_id, data).hide(); // 取新评论
                            if ($('#' + parent_id).find(".comment-children").length <= 0) {
                                $('#' + parent_id).append("<div class='comment-children'><ol class='comment-list'></ol></div>");
                            }
                            if (new_id)//new_id不为空的时候才会插入
                                $('#' + parent_id + " .comment-children .comment-list").prepend(data);
                            console.log('该评论为子评论,parent_id:' + parent_id);
                            parent_id = '';
                            //console.log(data);
                        } else {
                            data = $('#li-comment-' + new_id, data).hide(); // 取新评论
                            //console.log('该评论为母评论');
                            if (!$(comment_list).length) //如果一条评论也没有的话
                                $(respond).append('<div class="info-com">仅有<span class="comment-num">0<\/span>条评论<\/div><ol class="comment-list"><\/ol>'); // 加 ol
                            $(comment_list).prepend(data);
                            //console.log('评论内容:');
                            //console.log(data);
                        }
                        $('#li-comment-' + new_id).fadeIn(); // 显示
                        var num;
                        $(comments).length ? (num = parseInt($(comments).text().match(/\d+/)), $(comments).html($(comments).html().replace(num, num + 1))) : 0;
                        //console.log($('#comments h4').length);
                        // 评论数加一
                        TypechoComment.cancelReply();
                        $(textarea).val('');
                        $(comment_reply + ' a, #cancel-comment-reply-link').unbind('click');
                        click_bind(); // 新评论绑定
                        $(submit_btn).attr('disabled', false).fadeTo('slow', 1);
                        if (new_id){
                            $body.animate({scrollTop: $('#li-comment-' + new_id).offset().top - 50}, 500);
                        }else{
                            $body.animate({scrollTop: $('#comments').offset().top - 50}, 500);
                        }
                    }
                } catch(e) {
                    //alert('评论ajax错误!请截图并联系主题制作者!\n\n' + e);
                    window.location.reload();
                }
            } // end success()
        }); // end ajax()
        return false;
    }); // end $(comment_form).submit()
    function click_bind() { // 绑定
        $(comment_reply + ' a').click(function() { // 回复
            //$body.animate({scrollTop: $(respond).offset().top - 180}, 400);
            //console.log($(this).parent().parent().parent().parent());
            parent_id = $(this).parent().parent().parent().parent().parent().parent().attr("id");//parent()数量根据模板而定,否则评论嵌套可能有问题
            console.log("parent_id:" + parent_id);
            $(textarea).focus();
        });
        $('#cancel-comment-reply-link').click(function() { // 取消
            parent_id = '';
        });
    }
    function msg_effect(id) { // 出错
        $(submit_btn).attr('disabled', false).fadeTo('', 1);
    }
}
ajaxc();

注:上述代码中提示功能使用了 jquery 通知插件 toastr,如果你不想使用可将上述代码中的 toastr.info改成alert

出了一点问题

这样 在无instantclick的情况下 表现良好 但一添加进去之后...BOOM!!!

(中途 把评论者的每个li标签加上 date-no-instant 还有取消回复那里和评论框的输入区)

  • 从首页点进去之后评论文章 ,Ajax评论失效,当再次评论时,Ajax评论恢复正常 求解决方案

因为这个 机芯我捅咕了一下午 评论等级连升两级(现在看不着了测试的评论都删了) 还请泽泽dalao帮我看了一看 之后... 看到他TypechoComment这段系统自动生成的评论js位置不对(正常的都在head区 他的在评论下面) 然后告诉了我一个方案...

<?php $this->header('); ?>
模板的这个换成
<?php $this->header('generator=&template=&pingback=&xmlrpc=&wlw=&commentReply=&rss1=&rss2=&atom='); ?>

注: <?php $this->header('); ?> 位于模版的Header区(这不废话)

换了以后 TypechoComment的js就从Header里消失了 然后把这段js放倒评论模版里(一般都是comments.php)

然后把一些东西用php的输出改一下 这样下面的js就是个TypechoComment的副本(都是一样的 可直接放进去食用)

<!-- 感谢QQdie援助之爪 -->
<script type="text/javascript">  
(function () {
    window.TypechoComment = {
        dom : function (id) {
            return document.getElementById(id);
        },
        create : function (tag, attr) {
            var el = document.createElement(tag);
            for (var key in attr) {
                el.setAttribute(key, attr[key]);
            }
            return el;
        },
        reply : function (cid, coid) {
            var comment = this.dom(cid), parent = comment.parentNode,
                response = this.dom('<?php echo $this->respondId(); ?>'),
                input = this.dom('comment-parent'),
                form = 'form' == response.tagName ? response : response.getElementsByTagName('form')[0],
                textarea = response.getElementsByTagName('textarea')[0];
            if (null == input) {
                input = this.create('input', {
                    'type' : 'hidden',
                    'name' : 'parent',
                    'id'   : 'comment-parent'
                });
                form.appendChild(input);
            }
            input.setAttribute('value', coid);
            if (null == this.dom('comment-form-place-holder')) {
                var holder = this.create('div', {
                    'id' : 'comment-form-place-holder'
                });
                response.parentNode.insertBefore(holder, response);
            }
            comment.appendChild(response);
            this.dom('cancel-comment-reply-link').style.display = '';
            if (null != textarea && 'text' == textarea.name) {
                textarea.focus();
            }
            return false;
        },
        cancelReply : function () {
            var response = this.dom('<?php echo $this->respondId(); ?>'),
            holder = this.dom('comment-form-place-holder'),
            input = this.dom('comment-parent');
            if (null != input) {
                input.parentNode.removeChild(input);
            }
            if (null == holder) {
                return true;
            }
            this.dom('cancel-comment-reply-link').style.display = 'none';
            holder.parentNode.insertBefore(response, holder);
            return false;
        }
    };
})();
</script>

推测出的原理

然后 Ajax评论和instantclick就水火相容了 那...这是为什么呢? 下面是我的推断 不一定准确 如有错误请指出

我认为TypechoComment这段自动生成的js生成在head区里 inst不刷新这里(inst只刷新Body内内容) 会造成评论页面没有TypechoComment这段js 会造成异常 把这段js挪到body里就正常了,如评论模版(comments.php)

搜索的inst适配嘛...我会参照这篇文章继续进行 等这篇文章发布之后就开始动工 如果现在弄的话写文章的思路就没有了

yooooo 撸起袖子开始干

已有 17 条评论 (旧评论在前)
  1. xry
    回复
    xry
    2017-10-08 10:17 Windows XP

    帮机芯做回复测试

    1. 尚寂新 博主
      回复
      2017-10-08 10:19 Android 5.1

      一看你就没设置Gravatar头像2333

  2. 后宫学长
    回复
    2017-11-23 13:57 Windows NT10

    今年7月份之前我找不到一个支持全局PJAX,还支持AJAX评论的TP平台主题……
    当时记得有个LaShi主题支持。可惜后面没更新了……

    1. 尚寂新 博主
      回复
      2017-11-23 22:23 Android 5.1

      都是各位dalao们一个一个带动起来才跟着弄的23333

  3. longyujin9
    回复
    2017-12-27 16:39 Windows NT10

    我添加之后,评论正常,但是在回复别人的评论就跑到最上边去了,然后刷新又自己回去了

    1. 尚寂新 博主
      回复
      2017-12-28 22:22 Windows NT10

      需要自己改138行parent()的数量的 具体数量要看你主题怎样 或者可以把这个特征合法化23333(我就是这么干的懒得调直接当特征)

      1. 云武
        回复
        云武
        2018-02-27 17:40 Windows NT10

        机芯,这个数量是靠什么来确定的??我也卡在这里了

      2. 尚寂新 博主
        回复
        2018-02-27 17:52 Windows NT10

        一个一个慢慢试吧 其实我也不知道里面有啥规律(斜眼笑)

      3. 云武
        回复
        云武
        2018-02-27 17:53 Windows NT10

        不要这么搞笑,试了10个了,难道没个依据?

  4. 云武
    回复
    云武
    2018-02-27 14:39 Windows NT10

    机芯"妹纸",我路过~

    1. 云武
      回复
      云武
      2018-02-27 16:26 Windows NT10

      差不多研究好了,ajax testing.

  5. 而非规范化
    回复
    而非规范化
    2018-07-27 22:27 Windows NT10

    博文不错

  6. 欧文斯
    回复
    2018-07-30 15:07 Windows NT10

    感觉我移植的方式不对,不会跳到指定位置~~

  7. luss
    回复
    2019-10-15 15:01 Windows NT10

    请教,为啥我用了上面的代码也是放在footer下面,每次提交还是刷新了页面

    1. 尚寂新 博主
      回复
      2019-10-15 15:14 Android 9

      需要针对主题进行适配的,建议有些js的基础

  8. Veen Zhao
    回复
    2020-03-28 14:40 安徽省 Windows NT10

    学习一下~

  9. typeing
    回复
    typeing
    2023-05-10 15:25 广东省 Windows NT10

    测试一下

添加新评论 (Markdown Supported)
(ノ°ο°)ノ