Борьба за производительность и динамичность сайта может быть бесконечной. Чего только не сделаешь, только чтобы удержать зашедшего посетителя и превратить его в покупателя! Поэтому решил взять в руки AJAX. И начал с самого простого, как мне казалось сначала – решил обеспечить загрузку продолжения статьи (после тега <!—more—>) без перезагрузки страницы (AJAX + jQuery нам помогут). Об этом и пойдёт речь – будем писать плагин AJAX-Read-more.

Чтобы сразу было понятно, о чём статья – зайдите на сайт, на котором я экспериментировал. Нажмите на ссылку “Подробнее…” и увидите описываемый эффект.

Естественно, первое, с чего я начал – пошёл искать готовый плагин. И нашёл – Read more right here. Но, к сожалению, по ряду причин он подошёл только как заготовка для моего решения. Приступим.

Разбиваем статью на части

Причина простая – работать с частями статьи хочу как с DOM элементами. Посему определил в своём плагине фильтр:

add_action('init', 'ajax_read_more_init');

function ajax_read_more_init() {
    ...
    if(!is_admin()) {
        if(!is_ajax_read_more()) {
            add_filter('the_content', 'ajax_read_more_the_content', 11);
        } else {
            add_action('wp', 'ajax_read_more_wp');
        };
        ...
    };
};

function ajax_read_more_the_content($content) {
    if (!is_singular() and !is_feed() and !$more) {
        return 
            '<div id="post-entry-excerpt-' . get_the_ID() . '" class="entry-part">'
            . ajax_read_more_sanitize_content($content)
            . '</div>'
            . '<div id="post-footer-' . get_the_ID() . '" class="post-footer clear">'
            . apply_filters( 'the_content_footer', '' )
            . '</div>'
        ;
    } else {
        return $content;
    };
};

Как видно, фильтр на содержимое статьи пытаюсь поставить после “встроенных” фильтров (у них приоритет 10). И в фильтре делю статью на части: до more (точнее – уже до ссылки “Подробнее…”), включая саму ссылку, и всё, что после неё (например – социальные кнопки) – для их вставки применяю свой фильтр, который и использую в модифицированном плагине для социальных кнопок. Части разложил по разным div, чтобы на стороне клиента манипуляции были очевидными и максимальной простыми.

Пишем jQuery плагин

Теперь переходим к клиентской части – пишем плагин на jQuery, который и решит поставленную нами задачу:

var backgroundAction = false; 

jQuery.fn.AJAXReadMore = function (options) {
    var
        $ = jQuery,
        options = $.extend({ 
            animateSpeed: 'slow',
            errorMessage: "Error.<br/>Try again later.",
            errorClass: "loading-error",
            loadingClass: "loading",
            spacerClass: "loading-spacer",
            loadedClass: "loaded",
            contentElSelector: ".entry-part",
            moreElSelector: ".more-link",
            moreContainerSelector: ".more-link-container",
            onUpdateEvent: "onupdate",
            parentScrollableEl: $("html,body"),
            scroll: true,
            scrollToSelector: ".entry-header",
            scrollLowBound: 0,
            ajaxData: {
            }
        }, options); 

    return this.each(function() {
        var post = {
            data: $.extend(options.ajaxData, {
                'AJAX-mode':'1'
            }),
            moreLink: $(options.moreElSelector,this),
            navigation: $(options.moreContainerSelector,this)
                .add(options.moreElSelector,this)
            ,
            content: $(options.contentElSelector,this),
            el: $(this)
        },
        busy = false;
        if (!(post.content.length)) post.content=post.el;

        post.moreLink
        .unbind('click')
        .click(function(e) {
            if (busy) return false;
            var scroll = (options.scroll) && !(backgroundAction);
            busy = true;

            var newContent = post.content
                .clone(true)
                .html("")
                .hide()
                .insertAfter(post.content)
            ,
            spacer = newContent
                .clone()
                .addClass(options.spacerClass)
                .addClass(options.loadingClass)
                .insertAfter(newContent)
            ;
            
            post.scrollTo = $(options.scrollToSelector,post.el);
            if (!(post.scrollTo.length)) post.scrollTo=post.el;
            
            spacer.show();
            post.navigation.addClass(options.loadingClass);
            if (scroll) {
                spacer.animate( {height:($(window).height()) + "px"}, options.animateSpeed );
                if ((post.scrollTo.offset().top - options.parentScrollableEl.scrollTop() > options.scrollLowBound)) {
                    options.parentScrollableEl.animate({scrollTop: post.scrollTo.offset().top+ "px"}, options.animateSpeed);
                };
            };
            $.when(
                $.ajax ({
                    type: "GET",
                    url: post.moreLink.attr('href'),
                    dataType: "html",
                    cache: true,
                    data: post.data
                }),
                post.scrollTo,
                options.parentScrollableEl
            ).then(
                /*success:*/ function(args) {
                    /*args: [ data, "success", jqXHR ]*/
                    var data = args[0];
                    var dataObj;
                    var bodyEl = {length: 0};
                    try {
                        dataObj = $(data);
                        bodyEl = dataObj.find('body');
                    } catch(e) {};
                    var dt = {
                        url: post.moreLink.attr('href'),
                        referrer: $(location).attr('href')
                    };
                    var textStatus = args[1];
                    
                    if (bodyEl.length) {
                        dt = $.extend(dt, {
                            body: bodyEl.html(),
                            title: dataObj.find('title').text()
                        });
                    } else {
                        dt = $.extend(dt, {
                            body: data
                        });
                    };
                    
                    newContent
                        .html(dt.body)
                        .hide()
                        .slideDown(options.animateSpeed)
                        .trigger(options.onUpdateEvent)
                        .trigger('counter.hit', dt)
                    ;
                    spacer
                        .removeClass(options.loadingClass)
                        .slideUp(options.animateSpeed, function(){
                            post.navigation
                                .addClass(options.loadedClass)
                                .removeClass(options.loadingClass)
                            ;
                            $(this).remove();
                        })
                    ;
                    busy = false;
                },
                /*error:*/ function() {
                    /*args: [ request, "error", jqXHR ]*/
                    var request = args[0], textStatus = args[1];
                    newContent.remove();
                    post.navigation.addClass(options.errorClass);
                    spacer
                        .hide()
                        .addClass(options.errorClass)
                        .removeClass(options.loadingClass)
                        .html(options.errorMessage)
                        .fadeIn(options.animateSpeed)
                        .delay(1000)
                        .fadeOut(options.animateSpeed)
                        .delay(100)
                        .hide(options.animateSpeed, function(){
                            $(this).remove();
                            post.navigation
                                .removeClass(options.loadingClass)
                                .removeClass(options.errorClass)
                            ;
                        })
                    ;
                    busy = false;
                }
            );
            return false;
        });
    });
};

Назвал я свой первый jQuery плагин jQuery.AJAXReadMore. Очень хорошее и понятное описание правил хорошего тона при написании jQuery плагинов: anton.shevchuk.name.

Как видно, мы применяем наш плагин (естественно – по событию jQuery(‘document’).ready) к элементам, содержащим статьи (в моём случае эти элементы имеют класс post). А в самом плагине выделяю саму ссылку “Подробнее”, переопределяю для неё событие click. По этому событию делаю AJAX запрос, получаю продолжение статьи и вставляю его, предварительно скопировав контейнер анонса. На время загрузки использую промежуточный элемент – spacer. Он нужен больше для более “опрятной” анимации. Но его же использую для визуализации индикатора загрузки — устанавливаю для этого класс loading (“индикатор загрузки” логично привязывать через css, а не генерировать здесь лишние элементы, мне кажется). Ну и немного анимации добавил. Чтобы отвлечь посетителя на те несколько секунд, что подгружается продолжение, запускаю скроллинг окна – заголовок статьи к верней границе окна подгоняю.

Обратите внимание на генерацию кустарного события (trigger(‘onupdate’)), позднее поясню, откуда оно родилось.

А как же анимированный индикатор загрузки?

Итак, в CSS добавил следующее:

.loading-spacer {
    min-height:40px;
}
.entry-part {
    margin: 0;
    padding: 0;
}

.more-link.loading {
    display:none;
}
.loading-spacer.loading {
    background:url('images/ajax-loader.gif') no-repeat center top transparent;
}

.more-link.loaded {
    display:none;
}
.loading-spacer.loaded {
}

.more-link.loading-error {
}
.loading-spacer.loading-error {
    background:#A02020;
}

Сам индикатор генерируем с помощью удобного сервиса -www.ajaxload.info, рекомендую.

А что же на стороне сервера (wordpress – обрабатываем AJAX запрос)

Здесь мне пришлось заняться изучением событий (action) wordpress всерьёз. И переписал обработку AJAX запроса, сейчас в плагине она выглядит следующим образом:

add_action('init', 'ajax_read_more_init');

function ajax_read_more_init() {
    ...
    if(!is_admin()) {
        if(!is_ajax_read_more()) {
            add_filter('the_content', 'ajax_read_more_the_content', 11); // сразу после "встроенных" фильтров
        } else {
            add_action('wp', 'ajax_read_more_wp');
        };
        ...
    };
};

function ajax_read_more_wp() {
    if (have_posts()) {
        the_post();
        include('inc/ajax-response-html-wrappers/header.php');
        the_content(null, true);
        include('inc/ajax-response-html-wrappers/footer.php');
        die();
    } else {
        include('inc/ajax-response-html-wrappers/404.php');
    }
};

Для данной задачи (получение конкретной статьи без применения шаблона (темы)) лучше всего подходит событие wp. К этому моменту уже выполнен запрос, все параметры разобраны. Другими словами, вся механическая работа сделана, нам остаётся выполнить саму суть.

Обработка получилась – проще некуда. Второй параметр в the_content просто идеально подходит для нашей задачи – true в этом параметре как раз и приведёт к “отрезанию” анонса.

Обратите внимание на заголовки. Не ленитесь, указывайте явно кодировку, а также заголовки, обеспечивающие возможность кэширования на стороне клиента и прокси сервера.

AJAX: GET или POST?

Для данной задачи однозначно – GET. Просто потому, что кэшируются GET ответы. А мы преследуем цель обеспечить максимальный комфорт для посетителя нашего сайта, не так ли? Посему всегда выбирайте GET, если только нет жёсткой необходимости использовать POST.

Вновь загруженное содержимое и прочие плагины на стороне клиента

На первый взгляд почти всё – всё загружается, прокручивается, всё замечательно. Но я использую плагин fancy gallery, да и не только. И для картинок в “подгруженном” содержимом, естественно, он не применялся. А должен применяться. Вот и пришло время вернуться к trigger(‘onupdate’).

Итак, для вновь подгруженного содержимого я инициирую кустарное событие (onupdate). Ну а те плагины, которые должны обработать загруженное содержимое на стороне клиента, должны обработать это событие. Поэтому вносим изменения в плагин fancy gallery:

        jQuery('div.fancy-gallery a',this).each(function() {
            var $this = jQuery(this); 
            $this.attr('rel', $this.parent().attr('id'));
            var $this = jQuery(this); 
            $this.attr('rel', $this.parent().attr('id'));
        });

...

        // Add Fancy Classes to single items:
        jQuery('a',this).each(function() {
            // filter items
            if ( ... ) return;

            // shorter access path
            var $lnk = jQuery(this);
            var $img = $lnk.find('img'); 

            // Add the fancybox class
            $lnk.addClass('fancybox');

            <?php If ($wp_plugin_fancy_gallery->get_option('associate_single_images')) : // Give em a rel attribute ?>
            if ($lnk.attr('rel') == '' || $lnk.attr('rel') == undefined)
                $lnk.attr('rel', 'single-image');
            <?php EndIf; ?>

            <?php If ($wp_plugin_fancy_gallery->get_option('use_as_image_title') == 'alt_text') : // Copy the alternate texts ?>    
            $img.attr('title', $img.attr('alt'));
            <?php ElseIf ($wp_plugin_fancy_gallery->get_option('use_as_image_title') == 'caption') : // Copy the captions ?>
            if (caption = $lnk.parent('.wp-caption').find('.wp-caption-text').html())
                $img.attr('title', caption);
            <?php EndIf; ?>

            <?php If ($wp_plugin_fancy_gallery->get_option('change_image_display')) : ?>
            $img.css('display', 'inline-block');
            <?php EndIf; ?>

            // Copy the title tag from link to img
            $lnk.attr('title', $img.attr('title'));
        });

        jQuery('a.fancybox',this)
            .unbind('click')
            .fancybox({...});

        jQuery('a.fancyframe',this)
            .unbind('click')
            .fancybox({...});

    });
};

jQuery(function() {
    $(this).addFancyGallery();
    $('#content').delegate('', 'onupdate', function(e) {
        $(e.target).addFancyGallery();
    });
});

Как видно, нам пришлось оформить код как очередной плагин jQuery. И затем мы вешаем обработчик события onupdate на контейнер, содержащий все статьи и анонсы на странице. Но повторно плагин применяем только к тому элементу, содержимого которого изменилось (e.target), что правильно.

Итого, на этом первый опыт применения AJAX + jQuery + WordPress закончен. Плагин выложен в репозиторий wordpress.

Сейчас плагин возвращает корректный html код (включая заголовки). Сделал в частности для того, чтобы было где передать title (для счётчиков необходимо).

the_content vs the_excerpt

Некоторые темы используют для архивов не the_content, а the_excerpt. На момент корректировки статьи плагин ещё не обрабатывает такие анонсы, но в версии 3.0.0 уже планирую добавить поддержку the_excerpt.

Отзывы » (106)

  1. В обработке запроса на стороне сервера в случае ошибки пришлось внести коррективы:

    		Header('HTTP/1.0 404 Not Found');
    		Header('Content-type: text/html;charset=' . get_bloginfo('charset'));
    		Header('Last-Modified: ' . date(DATE_RFC1123));
    		Header('Cache-Control: no-cache');
    //		пришлось отказаться из-за проблем с плагином кеширования - ответ кешировался и отдавался уже без http 404
    //		wp_die(false, false, array('response'=>404));
    		die();
    

    Пришлось отказаться от wp_die в пользу die по следующей причине: ответ wp_die кешируется плагинами семейства Hyper Cache, и из кеша отдаются уже с HTTP 200, а не с HTTP 404.

    И ещё одна корректировка. Код инициализации плагина заменил. Было:

        jQuery(function() {
           $('.post').AJAXReadMore(); 
        });   
    

    Стало:

    jQuery(function() {
    	jQuery('#content')
    		.delegate('', 'onupdate', function(e) {
    			jQuery('.post', e.target).AJAXReadMore();
    		})
    		.trigger('onupdate');
    });
    

    Как видно, обеспечил корректную обработку и динамически подгружаемого содержимого.
    Пока всё.

  2. Плагин одобрен и выложен в репозиторий wordpress — AJAX Read More. Буквально в течение первых дней получил очень лестный отзыв в форуме на wordpress, приятно, однако :-).
    P.S. В репозиторий уже выложил версию 1.1.0 плагина, код поменялся, в статье его править не буду, идеология осталась прежней.

  3. Поправил свой плагин. Теперь всё, что он отдаёт (особенно в ответ на AJAX запрос) пропускаю через следующую функцию:

    function ajax_read_more_sanitize_content($content) {
    	return 
    		preg_replace(
    			'/<p>\s*<\/p>/s',
    			'',
    			force_balance_tags($content)
    		)
    	;
    }
    

    Суть в том, что при любых попытках разорвать содержимое по какому-либо тегу (в моём случае — по ссылке с классом more-link) существует вероятность того (стремящаяся к 100%), что в каждой из частей останутся незакрытые теги. И чтобы однажды в результате AJAX запроса не «развалилась» вёрстка сайта, решил принудительно закрывать все теги. Заодно и пустые абзацы в расход (они при закрытии тегов часто появляются).
    В версии плагина 1.1.2 отдаю уже «обработанный» контент, пока сбоев не замечено.

  4. Поступил комментарий, правда — к другой статье. На сайте автора успешно функционирует мой плагин AJAX Read More, нажмите у него на ссылку «Читать далее» — и увидите :-). Приятно, однако…

  5. Наткнулся на любопытный (по своей краткости) плагин, облегчающий использование ajax в Ваших собственных плагинах — AJAX Extend:

    <?php
    add_action( "wp", "ajax_operation" );
    
    function ajax_operation()
    {
    	/*
    	 * ajax_extend_mark : 
    	 * ajax_extend_action ��
    	 */
    	if(isset($_REQUEST["ajax_extend_mark"]))
    	{
    		$function_name = $_REQUEST["ajax_extend_action"];
    		if(!function_exists($function_name))
    			return;
    		call_user_func($function_name);
    		die();
    	}
    }
    ?>
    

    Со стороны клиента в url достаточно дописать параметры ajax_extend_mar и ajax_extend_action — и на стороне сервера будет вызвана Ваша функция на этапе («событии») wp.

  6. Николай:

    Поставил, но идет загрузка и на этом все.

  7. Ваш сайт сейчас по-прежнему ничего «не отдаёт», «виновника» не нашли?

  8. николай:

    Нет не нашел. А можно ли сделать без плагина читать далее без перезагрузки

    • Можно конечно. Просто придётся все те же действия в файл functions.php темы перенести. Для начала нужно заставить работать сайт без плагина. И выяснить версию PHP. Для начала давайте выясним, в плагине ли дело. Переименуйте папку с плагином и попробуйте снова получить доступ к сайту. Если при этом сайт будет нормально работать, уточните версию PHP на Вашем хостинге и сообщите мне её пожалуйста (лучше — здесь). Версия плагина, кстати, у Вас какая?

  9. def01:

    Добрый день, обнаружил несовместимость данного плагина с Social Share Buttons plugin, при нажатии на «Прочитать остальную часть записи» отображает только соц. кнопку ( А в целом отличный плагин, работает как часы)

    • Я этот плагин использую, но мне пришлось его несколько «допилить». Проблема, безусловно, не в плагине, а в WordPress. Дело в том, что WordPress не предусматривает специальных фильтров для «подвала» статьи, перед анонсом и так далее. Поэтому и плагины типа Social Share Buttons вынуждены вешать свои фильтры на the_content, и дописывать свой код по своему. Естественно, у каждого плагина подход свой.
      В дальнейшем я поправлю тему (а может и отдельным плагином сделаю — ещё не решил), и там уже повешу свой фильтр на the_content, в котором дорисую новые sidebar: post_footer, post_header и так далее. Именно sidebar, чтобы в них можно было виджеты визуально добавлять в консоли WordPress. И плагины типы Social Share Buttons буду целпять через механизм виджетов к «телу» статьи, так гибче. Сейчас же в коде (нижняя выдержка кода в статье) вызываю:

      apply_filters('the_content_footer', '')
      

      Таким вот образом сам формирую «подвал» статьи. И плагин Social Share Buttons поправил с целью использования данного фильтра для дописывания кнопок в статью. Дело в том, что иным способом унифицированно отделить статью от кнопок и прочих прелестей других плагинов не смог — не вижу решения. Поэтому и оформил «подвал», который, кстати, не перезагружаю через AJAX — он остаётся при подгрузке статьи неизменным.
      Если Вам требуется плагин Social Share Buttons, совместимый с моим плагином — сообщите, вышлю или здесь выложу текущую версию.
      P.S. А в дальнейшем, как уже писал, перепишу механим интеграции «контролов» в тело статей на виджеты и сайдбары. Однако не берусь сообщить, когда до этого руки дойдут. И плагин, который создаст описанные sidebar, и буду рекомендовать к использованию. А также буду просить разработчиков плагинов обеспечить поддержку его функционала в своих плагинах. Пока же решение почти «кустарное», поэтому выходить на разработчика Social Share Buttons просто не с чем, только отвлекать человека от полезного всем дела.

  10. Николай:

    Плагин заработал, спасибо вам большое. Смотрел вашу статью, читаем архив без перезагрузки страницы, хотел реализовать у себя на блоге, но безуспешно, не могли бы вы помочь разобраться?

  11. Hi Dear Sergey.
    First of all see my Website… In each post I have 3 Read more button. But I have only one tag in the post source code. Whats the problem???
    When I use the old version of your plugin «ajax read more» this problem will be fixed… And one read more button wil be appeard!!! But today I installed last version of Ajax read mor, but wp connot activate it. And this error showed up while activating:

    Plugin could not be activated because it triggered a fatal error.
    Parse error: syntax error, unexpected T_FUNCTION in /home/linkcom/public_html/wp-content/plugins/ajax-read-more/ajax-read-more.php on line 32

    I waiting for your help. Tnx a lot.

    • Sorry for my english :-)
      The latest version (1.3.0) uses PHP 5.3 (lambda functions). Please use PHP 5.3 in the future. Version 1.3.1 — only for you — for older versions of PHP. Please update to version 1.3.1 and send information to me.
      2 or more «more» button — this is a compatibility issue (my plugin and your theme). My RegExp to «more» link:

      preg_match('/\A(.*)(<a[^>]+?href="[^"]*?#more-'.get_the_ID().'"[^>]+?>.*?<\/a>)(.*)/s', $content, $post_parts)
      

      But Your theme generates (a …) without (/a). RegExp for You:

      preg_match('/\A(.*)(<a[^>]+?href="[^"]*?#more-'.get_the_ID().'".*?(?:(?:\/>)|(?:>.*<\/a>)))(.*)/s', $content, $post_parts)
      

      Version 1.3.1 — with this regular expression. Check it out, please!
      And please, show me your original content of link «more».

      • thanks for your help.
        I fixed this problem with this step’s
        but this information is necessary: my wp version is 3.2.1 | my server php version is 5.2.x
        Step 1.
        I installed the Ajax Read More Ver.1.3.1 but not activating

        Step 2. (for fixing 3 read more button on each post)

        I Found this line in ajax-read-more/ajax-read-more-core.php

        preg_match('/\A(.*)(<a[^>]+?href="[^"]*?#more-'.get_the_ID().'".*?(?:(?:\/>)|(?:>.*<\/a>)))(.*)/s', $content, $post_parts) 

        and replace with:

        preg_match('/\A(.*)(<a[^>]+?href="[^"]*?#more-'.get_the_ID().'"[^>]+?>.*?<\/a>)(.*)/s', $content, $post_parts) 

        Step 2. (for kill the php version alert and error)

        I found this in ajax-read-more/ajax-read-more.php

        $min_php_version = "5.3.0";

        and chenged it to:

        $min_php_version = "5.2";

        then Activate the plugin without any problem.!!

        thanks mr. Sergey for your Guide.
        Good luck.

  12. Получил приянтное письмо — плагин мой включили в каталог Softpedia. У меня теперь и там есть своя страничка, пусть и скромная пока :-).

  13. Николай:

    Добрый день Сергей Сергеевич. А вы не подскажите как сделать в вашем плагине, обратную функцию, «свернуть пост»?

  14. Serg:

    Заюзать к сожалению, не смог — требует ПХП 5,3. :(
    Сергей, а есть ли острая необходимость в 5,3?
    Обновлять ПХП с 5,2 — не вариант — под него нет и не будет ЗЕНДа.

    • Сергей, PHP 5.3 использую исключительно ради лямбда функций и замыканий, так код плагина получается более читабельным.
      Версия 1.3.1 на самом деле как раз будет работать на PHP 5.2 — нужно только в самом начале php файла поправить $min-php-version на 5.2.
      В новых версиях на php 5.2 вероятнее всего не вернусь…
      P.S. Сергей, откуда информация, что под 5.3 никогда не будет Zend Studio & Framework? Не поделитесь ссылочкой?

    • Откатил плагин на версию PHP 5.2. Сейчас в репозитории — промежуточная версия с заготовкой консоли управления, на днях доделаю обратное «сворачивание» статьи…

  15. Ден:

    Такая ошибка при активации:

    Warning: include_once(admin\admin.php) [function.include-once]:
     failed to open stream: No such file or directory in 
     ..../plugins/ajax-read-more/ajax-read-more-core.php on line 18
    Warning: include_once() [function.include]:
     Failed opening 'admin\admin.php' for inclusion (include_path='.:/usr/local/share/pear')in
     ...../plugins/ajax-read-more/ajax-read-more-core.php on line 18
    

    Возможно, дело в том, что wordpress установлен не в корне, а в папке, надо поправить путь до admin/admin.php? На другом сайте нормально активировалась, но не находит ссылки read more. Пытался добавить #content и .post в тему, но без успеха. Может сделать альтернативный вариант поиска таких ссылок? Если не получается автоматически, пользователи могли бы добавить id вроде #read-more-ajax на такие ссылки, а оно пусть их находит.

    • Касательно пути до admin/admin.php — не должно быть таких проблем. Загрузка выполняется относительно текущего каталога, ни разу не сталкивался с подобной проблемой. Можно, безусловно, организовать загрузку относительно WP_PLUGIN_DIR, но ДОЛЖНА работать относительные пути. Опишите пожалуйста полные пути до admin.php и до ajax-read-more-core.php.
      По поводу проблем с «обнаружением» ссылок. Дайте пожалуйста ссылку на Ваш сайт, посмотрю на генерируемый html, тогда смогу дать рекомендации / внести корректировки в плагин. По стандартам кодирования WordPress ссылка «читать далее» должна иметь класс more-link. Именно их я и «ищу». О возможных сложностях с используемой Вами темой смогу сообщить только после того, как Вы сообщите ссылку на Ваш сайт.
      P.S. глюки при публикации кода в комментариях поправлю на днях, недавно поставил плагин…

      • Ден:

        Путь до плагина дефолтный кроме того, что вордпресс установлен в папку «do». Т.е. /do/wp-content/plugins/ajax-read-more

        Как мне сделать относительно WP_PLUGIN_URL?

        Тему починил, добавив по вашей подсказке «more-link».

        Урл дать не могу, блоги видны в корпоративной сети только.

        • Давайте разберёмся.
          - В том блоге, где wordpress установлен в корень, сейчас всё работает?
          - Какая версия плагина у Вас установлена? Последняя версия — бета, но уже со страницей опций.
          - Страница опций отображается? На русском (при условии, что у Вас локаль русская для блога установлена)?
          - тема поддерживает «подвал» (wp_footer)? Если нет — в опциях плагина следует выбрать размещение скриптов в head, а не в подвале.
          Если проблема всё ещё осталась, вышлите хотя бы мне на почту (sergey.s.betke@novgaro.ru) сгенерированный html для какой-нибудь страницы, на которой плагин должен работать (со ссылками — more-link).

          • Ден:

            Установлена последняя версия, сегодня обновил. Блог тоже последний 3.2.1, русская локаль установлена. Тема с футером. Скрипты нормально подгружаются. В опциях страницы плагина почему-то нет! Всё-таки с путями где-то косяк. При этом у всех других плагинов нормально отображаются сеттинги, например, у меня установлен RusToLat (можно там посмотреть как они пути прописывают).В целом нормально работает после того, как я поправил тему, но не видно лоадера (думаю, тоже проблема с путём).И ещё проблема с разделом поиска обнаружилась сегодня: ссылка «читать дальше» присутствует для больших записей, работает через ajax, но выглядит всё неправильно. Похоже не срабатывает фильтр на сервере для search-archive, т.к. в коде я не вижу «read-more-container». В архиве, в тег-архиве и в категории-архиве всё нормально при этом.

          • Ден » опубликовал в репозиторий версию 1.4.2, заменил в include \ на /. Я так понимаю, у Вас на проблемном сервере стояла не windows система? на windows системах работает успешно и так, и так, а вот на linux… Проверьте пожалуйста 1.4.2, сообщите пожалуйста результат. Заранее благодарен.

          • Ден:

            После обновления с путями почти всё порешалось. Плагин смог активироваться на том сайте, который установлен в папку.Осталась проблема с search archive (писал выше).И возникла новая (на том вордпресс, что установлен в папке): при нажатии читать дальше страница зависает (я так понимаю javascript или jQeury уходят куда-то в бесконечный цикл). Видел такое с флэш-плагином, но чтобы javascript завесил страницу — это первый раз :) Собираюсь отключать в js всякие animation и прочие штуки, пока не найду где вешается. О результатах тестов сообщу.И ещё пожелание от пользователя для будущих версий: добавить в опции выбор прокрутки на загрузку (сейчас уходит на начало статьи, если превью по высоте больше экрана — выглядит как глюк, уезжает вверх). Выбор можно сделать такой: «прокручивать на начало статьи», «прокручивать на начало подгруженного контента», «прокручивать на N пикселов», «отключить анимацию прокрутки».

        • И по поводу .more-link. приведу строку из get_the_content:

          $output .= apply_filters( 'the_content_more_link', ' <a href="' . get_permalink() . "#more-{$post->ID}\" class=\"more-link\">$more_link_text</a>", $more_link_text );
          

          Другими словами, если какие-либо the_content_more_link фильты Вашей темы или используемых плагинов не убивают класс на корню — он и так должен присутствовать. По этой причине и решил не давать других возможностей выделения ссылки…

        • Сегодня вечером буду разбираться с путями. Экспериментировать смогу только с Вами, у меня все блоги стоят в корне, так уж сложилось.
          Странно вот что. Если скрипты прописываются нормально (раз всё работает в принципе), тогда и css, и картинка загрузки соответственно должна корректно отображаться. Дополнительные вопросы:
          - какой браузер используете?
          - screen.css из плагина успешно подключается?

          У Вас не отображается анимация при загрузке, я правильно понял? Сейчас использую следующий CSS код:

          .entry .loading{
          	background:url('images/ajax-loader.gif') no-repeat center top transparent;
          }
          

          Как видно, подразумевается, что статья вставлена в div с классом .entry. Если в Вашей теме это не так, поправьте screen.css, например — так:

          .loading{
          	background:url('images/ajax-loader.gif') no-repeat center top transparent;
          }
          

          Сейчас выкладываю очередную сборку, в которой screen.css уже именно такой.

        • Денис, с лечением бага с зацикливанием плагина (чего быть не должно в принципе, не имею циклов в коде, кроме циклом анимации из jQuery) не смогу помочь без html кода страницы, на которой наблюдается подобное поведение. Пожалуйста, вышлите мне на почту или выложите пожалуйста сюда (код можно обрамить [ sourcecode lang="html" ]код[ /sourcecode ], только без пробелов) html код страницы. Вслепую диагностика в этом случае представляется мне невозможной.

  16. руслан:

    Здравствуйте! У меня проблема с вашим плагином: он работает как надо, но почему то выводит после «читать далее» кракозябры. В чем может быть проблема, где копать?

  17. Денис, спасибо большое за тестирование и предложения по улучшению. Для начала — по «багу» со страницей поиска. Данный баг может всплывать не только на странице поиска, а всегда, когда используется the_excerpt вместе the_content. В частности, у моей жены на сайте при генерации страницы поиска вижу следующий код в теме (как правило — index.php, или search.php):

    if (is_search()){
        the_excerpt();
    } else {
       the_content('Подробнее...');
    };
    

    Сейчас плагин вешал свой фильтр только на the_content. the_excerpt не хотел бы обрабатывать по ряду причин: используется и в виджетах (типа «последние статьи»), и такая доработка может привести к проблемам в целом ряде плагинов.

    Посему — предложение следующее. Предлагаю Вам, если Вы действительно хотите, чтобы на странице результатов поиска работал мой плагин, заменить в теме указанный выше код (при генерации страницы результатов поиска — либо search.php, либо в index.php приведённое выше условие) на использование the_content вместо the_excerpt.

    Ведь the_excerpt рвёт содержимое статьи через определённое количество символом, да и ссылки .more-link в этом случае просто не будет.

    Сообщите пожалуйста, помог ли рецепт.

    По поводу прокрутки. Плагин прокручивает к началу статьи только в том случае, если начало статьи ниже верхней границы окна. В противном случае никакого скроллинга нет. Прошу Вас, вышлите мне всё-таки кусок html, с которым мой плагин так странно себя ведёт.

    Но опцию действительно имеет смысл добавить. Пока склоняюсь только к двум вариантам: «скроллировать к началу статьи» (как сейчас и есть), или «скроллировать к началу продолжения». Можно ещё один вариант добавить — «скроллировать к началу продолжения, если начало статьи за пределами окна». Также могу ввести ещё одну опцию — «не выполнять скроллинг, если его величина менее чем XXX пикселей». Я так понимаю, Вам именно последняя опция и требуется, с учётом длинный «анонсов»? Сообщите пожалуйста Ваше мнение.

  18. Опубликовал в репозитории wordpress версию 1.5.0 — добавил опцию «Не скроллировать до«. Теперь Вы можете указать минимальное количество пикселей, на которое будет выполняться скроллинг (чтобы скроллирование на 50 пикселей не выглядело как «глюк», как Вы и писали).

    В ближайшей версии (точнее — 1.6.0, ведь функционал меняется) добавлю возможность отключать скроллирование полностью (сам jquery плагин у меня давно уже такую опцию поддерживает, по сути — осталось на страницу опций добавить).

    По поводу выбора — куда скроллировать, jquery плагин, опять-таки, уже сейчас принимает селектор, определяющий элемент, до которого будет выполняться скроллинг, нет у меня пока только возможности на странице опций указать его.

    Итого, в следующей версии:

    • возможность отключения скроллирования
    • возможность явного задания селектора элемента, до которого будет выполняться скроллинг
    • возможность редактирования сообщения об ошибке (в случае ошибки выполнения AJAX запроса)

    P.S. Денис, буду Вам крайне благодарен за результаты тестирования версии 1.5.0.

  19. Ден:

    Версия 1.5.0 — немного поломаная.В 7-й строчке ajax-read-more.js надо поменять $ на jQuery (т.к. по-умолчанию wordpress jQuery работает в safe mode).Всё ещё проблема с ссылками read-more в результатах поиска в блоге. Я понимаю, что у вас на туристическом сайте её не видно, т.к. нет ссылок read-more  в поиске. Но во многих темах они есть. И надо их тоже фильтровать через тот же фильтр, что и на главной..Спасибо за новую опцию, хотя она у меня не работает, поэтому я просто закомментил анимацию в js пока.

    • Ден » несовместимость с jQuery safe mode исправил — версия 1.5.1. Спасибо за информацию.
      Поясните пожалуйста, что значит «на работает новая опция»? я её тестировал, прописываем, скажем 200 px, и скроллинга не будет, если требуется проскроллировать меньше 200 px. Или я не понял суть Вашей пролемы? Поясните пожалуйста, что на самом деле требовалось.

  20. Опубликовал версию 1.6.0 — добавлена опция отключения скроллинга.

  21. Уже 1.7.0 — добавлена опция кастомизации сообщения об ошибке в случае ошибки загрузки продолжения статьи по AJAX запросу.

  22. Денис, только что опубликовал версию 1.9.0. Скрипты, как и раньше остались прежними, но добавил опцию выбора элемента, до которого скроллировать страницу при подгрузке статьи. Можно указать произвольный jQuery селектор, либо выбрать один из двух предлагаемых вариантов — к заголовку статьи (как и было), к загружаемому продолжению статьи (как Вы и предлагали). Ещё одно Ваше пожелание реализовано :-)
    P.S. А с поиском — от Вас по-прежнему требуется пример html кода Вашей страницы с результатами поиска, анализ темы проблем не выявил, подозреваю плагины…

  23. Ден:

    Уже пользуюсь прокруткой к продолжению на трёх блогах - спасибо! :) Опцией «Прокручивать на (введите число пикселов, 20 по умолчанию) вниз» — пользовался бы тоже ;) Такая опция «привлеки внимание к лоадеру» была бы самая правильная и удобная для юзера, я думаю. Там, кстати, ещё слэши виндовые остлись в файле core, надо бы поправить. В общем, установил эту тему и плагин на этот маленький блог: тут видно все ошибки, про которые я говорил. Никаких лишних плагинов не установлено.http://10-13.ru/category/fotografii/ - тут нормально «читать далее»http://10-13.ru/?s=%D1%84%D0%BE%D1%82%D0%BE - тут плохо.Спасибо за классный плагин, кстати, уже сейчас многим будет полезен! :)

    • Денис, огромное спасибо за тестовый блог!
      - Сегодня ошибки с «виндовыми» слешами поправлю, выложу версию 1.9.1, но — вечером.
      - ошибки хорошо видны в блоге, на нём и протестируем :-)
      - по поводу работы плагина со страницы поиска — работает, однако, хотя и с теми же глюками. (У меня IE8, дома протестирую на IE9).
      Пока следующее предложение: вечером выкладываю 1.9.1 с исправленными ошибками со слешами, Вы утром обновляетесь — и вместе завтра смотрим, как всё работает на странице поиска.
      - опция с прокруткой на несколько пикселей потребует от меня модификации jquery плагина, этим займусь уже завтра. На текущей версии это так же можно реализовать, но для этих целей потребуется разместить некий html элемент в том месте, к которому Вы хотите скроллинг (например — через position:relative или ещё как), и его селектор указать в настройках плагина — и будет работать уже сейчас :-)

    • Выложил 1.9.1, исправил слэши, надеюсь — на этот раз везде, уже и поиском их поисках. Осталось разобраться с поиком. На ie8 у меня плагин на Вашем тестовом сайте отрабатывает, хотя и результаты его работы появляются ниже, чем требуется.
      Однако, в html коде я действительно не вижу необходимой «обёртки» вокруг ссылки… А на обычной странице — вижу обёртку. Неожиданно…
      Наблюдая за поведением плагина в Вашей теме, пришёл к следующему выводу: целесообразно переделать анимацию загрузку, и не модифицировать html после загрузки никак, кроме установки / удаления классов и непосредственно вставки полученного содержимого. И для анимации использовать не котейнер со ссылком, а вставляемый до загрузки пустой элемент высотой в окно — в нём по центру и крутить индикатор. И по завершению загрузки саму ссылку не трогать, только класс ей или её котейнеру соответствующий добавить, ну и через css уже её прятать. Такой подход позволит решать, чего делать с ссылкой, уже в css, да и можно будет использовать ссылки на продолжение, явно к «телу» анонса не «прилепленные» (как в случае с Вашей темой — на серой «панели».
      Но переработку отложу до версии 2.0.0. Сейчас необходимо решить вопрос с поиском — в чём же проблема.
      А в html на странице поиска вот что вижу:

      <a href="http ://10-13.ru/2007/10/21/fotootchyot-13-let-klassu-10-13/#more-26" class="more-link">Читать дальше ></a></p>
      

      Обратите внимание на символ >. Он должен быть представлен как html entity &gt;, а он в «чистом» виде разгуливает. Поправьте пожалуйста либо саму тему, либо её локализацию (вероятнее всего — локализацию).
      Сначала подумал, что он (символ >) и есть проблема, что он не вписывается в регулярное выражение. Естественно — это не так. Но вспомнил про условие в фильтре:

      function ajax_read_more_the_content($content) {
      	if ((is_home() or is_archive()) and !$more) {
                          ...
      	} else {
      		return $content;
      	};
      };
      

      Вот, в чём дело, блин. Я и забыл про это условие совсем. Должно быть:

      function ajax_read_more_the_content($content) {
      	if ((is_home() or is_archive() or is_search()) and !$more) {
                          ...
      	} else {
      		return $content;
      	};
      };
      

      Сейчас поправлю и выложу 1.9.2. Буду благодарен Вам за тестирование. Сообщите пожалуйста результат.

    • Выложил 1.9.2. Условие переписал:

      	if (!is_singular() and !is_feed() and !$more) ...
      

      Проверьте теперь страницу поиска, всё должно работать.
      P.S. Надо бы подумать над тем, чтобы и сценарии не цеплять к тем страницам, на которых они не будут использоваться. Поищу решение…

  24. Ден:

    Ух ты, здорово! Всё поправилось! :) Завтра остальные блоги обновлю. А можно ещё такой вопрос: у меня на одном сайте есть желание тоже использовать Ваш плагин, но, к сожалению, посты там не содержат «more»… Не подскажите, как мастер php, на что мне заменить вот этот ваш preg_match, чтобы разрезать пост, скажем просто по 400 символу, вместо more? Я бы туда и добавлял бы линк «читать дальше». 

    • Я рад, что всё получилось.

      Для статей и блога без more-link предлагаю следующее решение. Заменяем в теме вызовы the_content на the_excerpt. Количество символов для анонса в этом случае Вы сможете «отрегулировать» параметрами в консоли. А в моём плагине фильтр вместо the_content также придётся повесить на the_excerpt. И сам фильтр придётся переписать — ссылки то нет в отрывке… Сложнее всего будет по результатам AJAX запроса выделить остаток… В общем, нужно подумать.

      В любом случае, речь может идти только о поддержке the_excerpt наряду с the_content в плагине. Быстрого решения не обещаю.

    • Регулярку вообще убрал теперь. Не зря говорят — «учите матчасть». Наконец-то разобрался со вторым параметром get_the_content, он как раз и позволяет «отрезать» анонс от продолжения.

  25. Опубликовал 1.10.0. Добавил в админке возможность указания селектора для элемента, который будет скроллироваться. Как правило — это окно (которое соответствует элементу body). Но если у Вас тема в роли скроллируемого элемента использует другой элемент (сейчас это уже редкость, но всё же… и сам так иногда делал), Вы можете теперь указать его селектор в этом параметры — и плагин будет скроллировать всё правильно и в Вашем случае.

    P.S. Сегодня вечером планирую приступить к версии 2.0.0. В этой версии хочу переделать обработку ссылок .more-link. В частности — вероятнее всего избавлюсь от дополнительного контейнера, чтобы обеспечить большую совместимость с различными темами. И удалять элемент не буду при загрузке, планирую только класс ему менять, и уже через CSS его прятать (при этом Вы сможете изменить обработку ссылки после загрузки простой правкой правил CSS). Правила по умолчанию пропишу, буду прятать элемент ссылки. А анимацию буду делать не в контейнере ссылки, а в элементе, в который и подгружается содержимое.
    Следующим шагом, возможно, целиком избавлюсь от модификации исходного html кода, чтобы минимизировать вероятность несовместимости с темами.
    P.P.S Ну и после этого уже приступлю к следующей версии (3.0.0), в которой планирую ввести поддержку и the_excerpt, не только the_content.

  26. Уже опубликовал версию 2.0.0. Переработан в этой версии и jQuery плагин в том числе. Всё сделал, как и планировал (в предыдущем комментарии написал). На этом этапе уже не обрамляю .more-linkдополнительными тегами, чтобы не создать проблем некоторым темам. Сегодня вечером проанализирую возможность полного отказа от модификации исходного html кода плагином…
    P.S. Поддержка the_excerpt — нетривиальная задача. «Красиво» отделить «остаток» статьи от показанного отрывка — решения не вижу (с учётом возможных фильтров на the_excerpt от других плагинов и темы). Пока в голову приходит следующая идея: добавляем свой фильтр на the_excerpt. В нём — дописываем ссылку .more-link в конец отрывка. Но в ссылке, видимо, придётся явно указать через get параметр, что она включена в отрывок. И уже при обработке AJAX запроса по такой ссылке возвращать статью целиком. А в jQuery плагине при обработке таких ссылок не дописывать статью в дополнение к анонсу, а полностью замещать отрывок новым содержимым. Такое решение мне кажется пока наиболее гибким. Кстати, задачу по определению необходимости замещения анонса можно возложить на сервер, и от него уже и требовать включения в заголовок возвращаемого html кода некую meta с признаком необходимости полного замещения. Ну что же, буду пробовать версию 3.0.0.

    • Ден:

      Версия 2.0 мне не подошла ни на один блог. Всё ломается, можно глянуть там же на тестовом 10-13.ru. Откатился на 1.9.5, а потом ещё на 1.9.2 (т.к. в .5 добавляется лишний «p» где-то, наверное это для пользы, но если он уже есть — получается разрыв в тексте). Задачку с автоматическим «more» решил немного некрасиво, добавив код, который должен добавлять ваш плагин в отдельный фильтр ) Пока пойдёт. Посмотрим на версию 3.0. :)

      • Денис, с 1.9.5 — действительно, ошибся с приоритетом фильтра, поставил его ниже wptexturize, который и лепит лишние теги. В 2.0.0 этой ошибки нет. Но это не всё. Судя по тем ошибкам, что я вижу на тестовом сайте, используется жутко старая версия файла ajax-read-more-core.php, номера строк совсем не совпдают. Это ещё с тех времён, когда была проблема со слешами. Проверьте пожалуйста версию файла. Либо же — ответы на GET запрос приходят из кэша сервера. Если у Вас используется кэширование на тестовом сервере (не важно — плагином или средствами сервера) — сбросьте пожалуйста кэш.
        На самом деле с кэшем — мой косяк. У меня в плагине уже была предусмотрена возможность при переходе с версии на версию менять url для GET запроса, но при переходе на 2.0.0 забыл изменить url. Сейчас поправил, публикую версию 2.0.1. Попробуйте её сначала на тестовом сервера, только как минимум в браузере всё-таки кэш сбросьте перед испытанием новой версии.
        В следующей версии переделаю механизм контроля версий сценариев, чтобы забывать об этом реже :-)

      • Кстати, заодно прошу Вас поправить на тестовом сайте ссылку «Читать дальше», расположенную ниже статьи (в <span class="continue">). Если Вы добавите ей класс .more-link, то и она теперь (начиная с 2.0.0) должна работать корректно — через AJAX. Буду благодарен Вам, если поможете в тестировании и такого варианта.

      • Денис, прошу прощения!!! Сбросил кеш у себя на прокси — увидел реальную картину на Вашем тестовом сайте. Всё нормально с файлом, всё работает. Вижу, что Вы имели в виду под «развалилось». Сейчас изучаю особенности темы чтобы понять, где я был неправ.

      • Пока увидел только <div id="content"> со стилями из CSS position: relative; z-index: 20;. HTML генерится правильный, в том числе и после плагина. Попробую понять, что происходит с браузером, сравнивая 1.9 и 2.0 версии плагина.
        Кстати — в каком браузере наблюдаете результат? (у меня — IE8).
        Ради эксперимента — добавьте пожалуйста в CSS:

        #content {
            height: auto !important;
        }
        
      • Денис, пока Вы ещё не внесли изменений. Ситуация крайне любопытная. Нажимаем «Читать далее», — плагин отрабатывает, фото вижу, вёрстка не раздвинулась. Щелчок мышкой на содержимом — и вёрстка восстановилась, всё как и должно быть. Почему этот «глюк» не наблюдался на 1.9 — пока сказать не могу. На Вашем браузере эффект тот же?

    • Начитался в интернете умных мыслей. Предварительные выводы. Версия 1.9 удаляла контейнер с .more-link, что вызывало reflow в браузере. В версии 2.0 я уже ничего не удаляю, использую исключительно CSS стили. Применение стилей также должно принудительно вызвать reflow в браузере, чего я не наблюдаю.
      «Последняя» анимация выглядит следующим образом:

      .slideDown(options.animateSpeed, function(){
      	post.navigation
      		.addClass(options.loadedClass)
      		.removeClass(options.loadingClass)
      	;
      })
      

      Другими словами, после завершения анимации мы должны наблюдать reflow в браузере, и разметка в этом случае была бы восстановлена. Но мы этого не наблюдаем. Между тем, в CSS плагина правила таковы, что в результате вышеописанных действий display: none; — как было, так и останется. Возможно — поэтому reflow в браузере не наблюдаем, только redraw.
      Итак, требуется принудительно вызвать reflow в браузере по завершению анимации. В версии 2.0.2 пробую следующее решение:

      .slideDown(options.animateSpeed, function(){
      	$(this).hide().show(); // for reflow
      })
      

      Мерцаний в браузере не обнаружил, а reflow при этом должен быть.
      Итого — предлагаю Вам попробовать версию 2.0.2, которая на Вашей теме заставит браузер пересчитать layout после окончания анимации.

  27. Однако, Денис, на IE9 на тестовом сайте проблем нет, всё работает замечательно. Что ещё раз подтверждает — проблема в браузере, не выполнен reflow. Посему и стоит попробовать 2.0.2, буду благодарен Вам за установку новой версии на тестовый сайт.

    • Ден:

      Да, в 2.0.2 ситуация поправилась! Перешёл на него. Только вот в загружаемом контенте теперь появляется лишний «br» в начале (раньше, видимо, лишний перевод строки после more убирался в preg_match). И ещё раньше была такая клёвая анимация, когда загруженный контент подмнимался вверх на строчку, съедая лоадер. А теперь её нет…

      • Ден » Однако, тестовый блог обновлён (вижу по url к скриптам), а у меня в IE8 поведение прежнее (как и вчера было), в IE9 — всё нормально (но в IE9 и вчера всё было нормально.
        По поводу клёвой анимации: раньше контейнер со ссылкой уничтожался, что всё-таки не очень хорошо, что с ним делать — решать теме и владельцу блога в CSS. Но, тем не менее, есть возможность вернуть ту красивость — поменяю сегодня вечером местами контейнеры spacer и newContent. Тогда эффект будет даже ещё интереснее — текст будет выезжать снизу из-за пределов окна и «съедать» индикатор.
        Версия будет — 2.0.3.

      • Сейчас продолжение выделяется чисто средствами wordpress. Проверьте, что в статье Вы явно использовали <p> Я у себя отключил фильтр wpautop от the_content из за его излишнего вмешательства зачастую. Описанный Вами эффект — его рук дело.

        • Ден:

          Нет, автоформатирование постов мне нужно, т.к. у меня только голый текст. Это вызывает следующую проблему с плагином: more вставляется между двух параграфов, поэтому автоформат переводит этот отрезок в  «p текст1 br — more — br текст2 p» (можете сами посмотреть код) — ваш плагин разрезает эти br в  разные div — получается неправильно. Правильно статья выглядит на отдельной странице: «p текст1 p текст2 p» (потому что два перевода строки это «p», а не два «br» для автоформата. Т.е. br — получается тоже незакрытый тэг, разрезанный вашим плагином. В версиях с preg_match такой проблемы не было, т.к. походу он отрезал лишние переводы строки ещё до автоформата. Надо какой-то фикс и тут, который бы отрезал перевод строки до автоформата или удалял br в начале и в конце в форматированном тексте. А вот в этом блоге надо бы включить автоформат для комментов хотя бы — неудобно без параграфов читать и писать )))

          • Ден » Дело в том, что сейчас не мой плагин режет статью, а исключительно сам wordpress (the_content). Просто раньше я принудительно вызывыл следующую функцию:

            function ajax_read_more_sanitize_content($content) {
            	return 
            		preg_replace(
            			'/<p>\s*<\/p>/s',
            			'',
            			force_balance_tags($content)
            		)
            	;
            }
            

            ,
            где force_balance_tags — также API WordPress, the_content поему то вызывает этот фильтр только для хвоста.
            Если же обрамление more выглядит так:

            <p>анонс</p><!--more-->
            <p>продолжение</p>
            

            тогда ещё один фильтр wordpress — wpautop — ничего лишнего не вставит. Если будут лишние переносы строк — ждите сюрпризов от wpautop. Я на своём блоге его вообще отключил от the_content, добавив в function.php темы

            remove_filter('the_content', 'wpautop');
            

            .
            Безусловно, я могу вернуть принудительный вызов приведённой выше функции. Просто посчитал эту обработку излишней. Я подумаю, как вернуть её более правильно с точки зрения wordpress. На самом деле, исправления следует вносить в wpautop. В общем — ждите 2.0.4.

          • Однако, force_balance_tags всё-таки вызывается, тут я неправ… Тогда смысла в моей функции сейчас нет. Два решения, которые могу предложить — обрамять more явно тегами без переноса строки, либо же я могу добавить фильтр, удаляющие «лишние» <br/> вокруг <!--more-->.

          • Ден:

            Да, в каком-то плагине я видел подобную функцию, которая для собственной корректной работы приводила more к виду как у вас в примере, удаляя лишние p и br вокруг него.  Было бы неплохо добавить… Ждём 2.0.4 ))

  28. Изучая внимательно class-wp.php понял, что мои потуги с заголовками для кеширования несколько неуместны, и даже излишни. До события wp вызываются обработчики send_headers, и заголовки все уже сформированы. Внимательно следует посмотреть на метод send_headers, там всё логика wordpress по формированию заголовков. До отправки заголовков их можно поправить фильтром wp_headers. И логика 404 ошибки уже обработана, поэтому осталось только убить процесс без дополнительных заголовков. Посему всё несколько упростил.
    Даже для правильного ответа заголовки уже все добавлены, нет только Cache-Control. Я пока не понял из каких соображений WordPress никогда не добавляет Cache-Control сам. Делать это в этом плагине не резон, честно говоря. В дальнейшем, видимо, имеет смысл отдельный плагин для кеширования рисовать, сейчас этот заголовок из плагина убрал, его буду добавлять в ядро в send_headers (там эти заголовки формируются корректно только для feed почему-то), или плагином через фильтр wp_headers.

  29. Seb:

    Hi, how do I disable the animation loading effect? There isn’t an option in the settings. Thanks.

  30. Lee:

    I like plugin. It’s much better than other options I’ve been looking at. I have a few suggestions:Can you add an option to add a link to the full article below the expanded excerpt?Can you add an option to contract the expanded excerpt?
    Can you add an option to change the «<strong>Read More</strong>» text link to point to an external page?
    Here is an article that might help with the 3rd suggestion: WordPress, read more with external linkThank you for creating this plugin.

  31. ilgar:

    блог easyyou.ruне работае. какие настройки нужно сделать? 

  32. Dargas:

    Здравствуйте, Сергей Сергеевич!Большое спасибо, Вам за плагин.Это очень полезный и интересный плагин. 

  33. Шикарный плагин! Большое спасибо! Видел этот вывод  в именитых блогах Live Journal. Думал для WordPress его нет, а оказалось, что вы его создали. Случайно нашёл и установил на свой сайт, на котором последняя версия WordPress/Один только вопрос? У меня на сайте в блоге http://innka.info/blog/ , если нажать на кнопку «Читать далее» то появляется пробел между текстом до кнопки и после. На самой странице записи этот пробел не появляется Подскажите пожалуйста как его убрать? На вашем сайте пробела нет/

  34. И ещё плохо, что страницы в лайтбоксе не открываются. Открываются в обычном окне. Испытал другой похожий плагин — и там та же история.

  35. Иван:

    Подскажите, пожалуйста, скрываю внутренние ссылки через аякс для управления весом. Но не хотелось бы терять ПФ в яндекс метрике. Как правильно отправлять данные в счетчик я метрики, когда пользователь переходит по такой скрытой ссылке? Использую такой скрипт <script>$(‘.hidden-link’).replaceWith (function (){return’<a onclick=»return !window.open(this.href)» href=»‘+$(this).data (‘link’)+’» title=»‘+$(this).text ()+’»>’+$(this).html ()+’</a>’;})</script>

  36. Yvonneamema:

    https://www.youtube.com/watch?v=ZEmLVYyVtZ0

    ZEmLVYyVtZ0
    другой человек паук 4 играть
    играть в игру человек паук 2 бесплатно как в фильме
    вместе с человеком пауком
    мультик про человека паука и халка на мотоцикле
    купить детское полотенце человек паук

    Zyo5URtkTvc
    новый человек паук minecraft
    комиксы человек паук серия другой
    фильмы 2017 человек паук возвращение домой дата выхода
    скин черного человека паука для гта 4
    новый человек паук hd 1080p

Опубликовать комментарий

XHTML: Вы можете использовать следующие HTML теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags Связь с комментариями статьи:
RSS комментарии
Обратная ссылка