作品,记录 创建于2014年09月8日 [1,086]
博客主题更新v1.1,完美全站化AJAX

上一篇文章的全站式AJAX其实是不够完美的,而且脚本也很复杂,本来已经被我放弃了,但前几天我上一篇文章中来了一位不速之客:jimmy 提到另一种方式实现全站AJAX,就是PJAX。

对于PJAX,我虽早有耳闻但没去细看(当初托百度的福,让我搜到的全是垃圾!)。对于jimmy的网站,我当初只是随手点了评论上的连接进去看一下,随即发现全站AJAX整合得非常好让我对全站AJAX效果又重燃希望。碰巧过几天就是周末+中秋节+公司福利再放一天假,于是小长假连休4天,是个好机会。

花了三天时间终于搞定,过程就不说了。

本次更新后主题主要功能如下

全站式AJAX(包括评论)
HTML播放器(兼容移动设备)
自适应PC与iPad
NProgress进度条
timthumb自动缩略图
简易LightBox效果(图片可原图放大)

手机端的自适屏功能留到下次更新再做好了 XD

接下来简单分享下心得吧。

要打造良好体验的全站式AJAX博客,我觉得至少需要这么三样东西:

PJAX(封装PUSHSTATE + AJAX)插件:https://github.com/defunkt/jquery-pjax/
AjaxComments(Willin插件版):http://kan.willin.org/typecho/typecho-ajax-comments.html
NProgress进度条插件 :http://ricostacruz.com/nprogress/

当然其他的例如scrollLoading/LazyLoad(图片分屏加载插件),Audioplayer.js/Audio.js(HTML5音乐播放插件)等,有兴趣的自行选择。

官网都有简单的调用教程,应该不用我多说什么。

但有两点,我觉得大家一定会遇到的。

AjaxComments插件与PJAX冲突

解决方法嘛,自然就是把AjaxComments的脚本提取出来囖。
如果觉得提取有困难的,请看:

function ajaxcomments(){
    $body = (window.opera) ? (document.compatMode == "CSS1Compat" ? $('html') : $('body')) : $('html,body');
    var 
    comments_order = 'ASC',
    comment_list = '.comment-list',
    comments = '.comments-title',
    comment_reply = '.comment-reply',
    comment_form = '#comment-form',
    respond = '.respond',
    textarea = '.textarea',
    submit_btn = '.submit',
    new_id = '',
    parent_id = '';
    $(submit_btn).attr('disabled', false);
    click_bind();
    $(comment_form).submit(function() {
        $(submit_btn).attr('disabled', true).fadeTo('slow', 0.5);
        $.ajax({
            url: $(this).attr('action'),
            type: $(this).attr('method'),
            data: $(this).serializeArray(),
            beforeSend: function() {
                NProgress.start()
                $(comment_list).fadeTo(100,0.1)
            },
            complete: function() {
                $(comment_list).fadeTo(600,1)
                NProgress.done()
            },
            success: function(data) {
                var wait = 5;
                $submit = $('#comment-form .submit');
                var submit_val = $submit.val();
                function countdown() {
                    if (wait > 0) {
                        $submit.val(wait);
                        $submit.attr('disabled', true).fadeTo('slow', 0.5);
                        wait--;
                        setTimeout(countdown, 1000)
                    } else {
                        $submit.val(submit_val).attr('disabled', false).fadeTo('slow', 1);
                        wait = 5
                    }
                }
                $(countdown);
                try {
                    if (!$(comment_list, data).length) {
                        if (data.indexOf('Error') > -1) {
                            alert("评论发送过于频繁,请稍后再试。")
                        }
                    } else {
                        $(textarea).val('');
                        new_id = $(comment_list, data).html().match(/id=\"?comment-\d+/g).join().match(/\d+/g).sort(function(a, b) {
                            return a - b
                        }).pop();
                        data = $('#comment-' + new_id, data).hide();
                        $('#reply-to-' + new_id, data);
                        if (!$(comment_list).length) $(respond).before('<ol class="comment-list"><\/ol>');
                        parent_id ? (comments_order == 'DESC' && $('#' + parent_id + ' li').length ? $('#' + parent_id + ' li:first').before(data) : $(respond).before(data), parent_id = '') : $(comment_list + ':first').append(data);
                        $('#comment-' + new_id).fadeIn();
                        $(comments).length ? (n = parseInt($(comments).text().match(/\d+/)), $(comments).text($(comments).text().replace(n, n + 1))) : 0;
                        TypechoComment.cancelReply();
                        $(comment_reply + ' a, #cancel-comment-reply-link').unbind('click');
                        click_bind();
                        $('#author').length ? countdown() : $(submit_btn).attr('disabled', false).fadeTo('slow', 1);
                        $body.animate({
                            scrollTop: $('#comment-' + new_id).offset().top - 200
                        },
                        500)
                    }
                } catch(e) {
                    alert('Error!\n\n' + e)
                }
            }
        });
        return false
    });
    function click_bind() {
        $(comment_reply + ' a').click(function() {
            $body.animate({
                scrollTop: $(respond).offset().top - 180
            },
            400);
            h = $(this)[0].href;
            parent_id = 'comment-' + h.substring(h.indexOf('replyTo=') + 8, h.indexOf('#'));
            $(textarea).focus()
        });
        $('#cancel-comment-reply-link').click(function() {
            parent_id = ''
        })
    }
};

如果你直接使用这个js,记住针对自己的模板修改类名,不做修改是肯定无法使用的。因为我的类名是按照我个人习惯来搞的。

Typecho下回复按钮的问题

这个问题是,当你实现了全站AJAX和评论AJAX以后,发现点击评论上的‘回复’或者‘取消回复’会导致页面刷新。

当初我的AJAX评论还不是很稳定,时不时报错。跟jimmy交流的时候,他提到我会遇到这个回复按钮的问题(确实遇到了,但我还没到解决这个问题的时候),他直接给了我解决方案,赞一个XD。

原文地址:Typecho下回复按钮的问题

为了避免其他因素导致文章无法打开,我这里留一份底:

1.打开主题的comments.php
2.找到<?php $comments->listComments(); ?>
3.在前后加上<div data-no-instant>和</div>

如下

<div data-no-instant>
<?php $comments->listComments(); ?>
</div>

最后在comments.php的尾部加上以下代码

<script type="text/javascript">
//<![CDATA[
var 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('respond-post-286'), 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('respond-post-286'),
        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基础有兴趣,可以阅读: Typecho实现全站式Ajax的方法

这已经是最后一篇文章
Typecho实现全站式Ajax的方法
已有 9 条评论
  1. 沙发

    1. 顺便测试邮件 XD

  2. 真是个不借的方法。

    1. 看见你也用上了 :)

  3. JV JV

    代码溢出了。
    呃…… 评论表单placehold挡住了填写内容。

    1. 请问您是使用什么浏览器呢?我这边在chrome 和firefox ie10 下看均无问题。

  4. JV JV

    我用的 Firefox 32.0.3 ,
    placehold问题已经解决。代码没有换行。

  5. 感谢,已用上,折腾了几天,评论不好搞,索性弄了多说的

    1. 最新版的1.0 在ajax评论方面做了些修改,上面这些代码不能用(这些是0.9时代的东西)。

添加新评论
登录管理
︿