Посты по тэгу: Wordpress

Делаем ajax отзывы в WordPress, добавляем возможность загружать фото и добавляем рейтинг

11 апреля, 2020

В моем примере я использовал плагин ACF. Но тоже самое можно адаптировать под стандартные произвольные поля. Мои произвольные поля: rating — числовое поле, по умолчанию значение 5. (поле нужно для рейтинга). А так же поле город town.

Шаг 1.

Идем в functions.php и регистрируем новый post_type.

add_action( 'init', 'true_register_post_type_init' ); // Использовать отзыв только внутри хука init

function true_register_post_type_init() {
	$labels = array(
		'name' => 'Отзывы',
		'singular_name' => 'Отзыв', // админ панель Добавить->Отзыв
		'add_new' => 'Добавить отзыв',
		'add_new_item' => 'Добавить новый отзыв', // заголовок тега <title>
		'edit_item' => 'Редактировать отзыв',
		'new_item' => 'Новый отзыв',
		'all_items' => 'Все отзывы',
		'view_item' => 'Просмотр отзыва на сайте',
		'search_items' => 'Искать отзыв',
		'not_found' =>  'Отзывов не найдено.',
		'not_found_in_trash' => 'В корзине нет отзывов.',
		'menu_name' => 'Отзывы' // ссылка в меню в админке
	);
	$args = array(
		'labels' => $labels,
		'public' => true,
		'publicly_queryable' => false,
		'show_ui' => true, // показывать интерфейс в админке
		'has_archive' => false,
		'menu_position' => 20, // порядок в меню
		'supports' => array( 'title', 'editor', 'thumbnail')
	);
	register_post_type('testimonials', $args);
}

Шаг 2.

Здесь же, в functions.php добавляем ниже:

// Вывод уведомления, если есть записи на утверждение
// только для админов
if( current_user_can('manage_options') ){
	add_action( 'admin_notices', 'my_plugin_notice' );
	function my_plugin_notice() {
		$count_posts = wp_count_posts('testimonials');
		$countpanding = $count_posts->pending;// определяем количество записей на утверждении
		if ($countpanding>0) { //если что-то есть, выводим в адмнике уведомление
				?>
				<div class="updated">
					<p style="color:red; font-weight:bold; font-size:14px">Есть новые отзывы на утверждение! Количество: <?php echo $countpanding;?> </p>
					<a href="/wp-admin/edit.php?post_status=pending&post_type=testimonials">Посмотреть</a>
				</div>
				<?php
		}
	}
}

add_action( 'admin_menu', 'add_user_menu_bubble' );
function add_user_menu_bubble(){
	global $menu;

	// записи
	$count = wp_count_posts('testimonials')->pending; // на подтверждении
	if( $count ){
		foreach( $menu as $key => $value ){
			if( $menu[$key][2] == 'edit.php?post_type=testimonials' ){
				$menu[$key][0] .= ' <span class="awaiting-mod"><span class="pending-count">' . $count . '</span></span>';
				break;
			}
		}
	}
}

Этот код отвечает за уведомления в админке.

Шаг 3.

Создаем форму.

<form class="rr_review_form" id="featured_upload" method="post" action="#" enctype="multipart/form-data">
   <input type="hidden" name="rRating" id="rRating" value="0">
   <div class="form-footer clearfix">
      <div class="row">
         <div class="col-md-12">
            <div class="form-group animated-labels">
               <div class="input">
                  <input id="Name" class="form-control required" type="text" name="name" value="" required="required" placeholder="Ваше имя">
               </div>
               <span class="form-err"></span>
            </div>
         </div>
      </div>
      <div class="row">
         <div class="col-md-12">
            <div class="form-group animated-labels">
               <div class="input">
                  <input id="Town" class="form-control required" type="text" name="town" value="" required="required" placeholder="Ваш город">
               </div>
               <span class="form-err"></span>
            </div>
         </div>
      </div>
      <div class="row">
         <div class="col-md-12">
            <div class="form-group animated-labels">
               <div class="input">
                  <textarea id="ReviewContent" class="form-control required" name="text" rows="10" style="resize: none; overflow-y: hidden;" required="required" placeholder="Текст отзыва"></textarea>
               </div>
               <span class="form-err"></span>
            </div>
         </div>
      </div>
      <div class="row" data-sid="RATING" style="    margin-bottom: 20px;
         margin-top: 9px;">
         <div class="col-md-12">
            <label for="POPUP_RATING">Рейтинг</label>
            <div class="input">
               <div class="rating_wrap clearfix">
                  <div class="rating">
                     <span class="star rr_star glyphicon glyphicon-star-empty" data-current_width="20" data-message="Очень плохо" data-rating_value="1" id="rr_star_1"></span>
                     <span class="star rr_star glyphicon glyphicon-star-empty" data-current_width="40" data-message="Плохо" data-rating_value="2" id="rr_star_2"></span>
                     <span class="star rr_star glyphicon glyphicon-star-empty" data-current_width="60" data-message="Нормально" data-rating_value="3" id="rr_star_3"></span>
                     <span class="star rr_star glyphicon glyphicon-star-empty" data-current_width="80" data-message="Хорошо" data-rating_value="4" id="rr_star_4"></span>
                     <span class="star rr_star glyphicon glyphicon-star-empty" data-current_width="100" data-message="Отлично" data-rating_value="5" id="rr_star_5"></span>
                     <span class="stars_current" data-rating="0" style="width: 0%;"></span>
                  </div>
                  <div class="rating_message" data-message="Без оценки"> - Без оценки</div>
               </div>
            </div>
            <span class="form-err"></span>
         </div>
      </div>
      <div class="row">
         <div class="col-md-12">
            <label for="POPUP_RATING">Ваше фото</label>
            <div class="input">
               <input type="file" name="my_image_upload" id="my_image_upload"  multiple="false" />
               <?php wp_nonce_field( 'my_image_upload', 'my_image_upload_nonce' ); ?>
            </div>
            <span class="form-err"></span>
         </div>
      </div>
      <div>
         <button class="btn-lg btn btn-default" id="submitReview" type="button">Отправить</button>
      </div>
      <div class="result"></div>
      <span class="name-field">Вы не заполнили поле Имя</span><br>
      <span class="name-field2">Вы не заполнили поле Текст отзыва</span>
   </div>
</form>

Шаг 4. Добавляем скрипты.

$(document).on('click', '.rr_star', function() {
    var rate = $(this).data('rating_value');
    $('#rRating').val(rate)
});


$(document).on('mouseenter', '.rr_review_form .rating .star', function() {
    var $this = $(this),
        currentStarWidth = $this.data('current_width'),
        ratingValue = $this.data('rating_value'),
        ratingMessage = $this.data('message');
    $this.closest('.rating').find('.stars_current').width(currentStarWidth + '%');
    $this.closest('.rating_wrap').find('.rating_message').text(ratingMessage)
});
$(document).on('mouseleave', '.rr_review_form .rating', function() {
    var $this = $(this),
        dataRating = $this.find('.stars_current').data('rating'),
        ratingMessage = $this.closest('.rating_wrap').find('.rating_message').data('message');
    $this.find('.stars_current').width(dataRating + '%');
    $this.closest('.rating_wrap').find('.rating_message').text(ratingMessage)
});
$(document).on('click', '.rr_review_form .rating .star', function() {
    var $this = $(this),
        currentStarWidth = $this.data('current_width'),
        ratingValue = $this.data('rating_value'),
        ratingMessage = $this.data('message');
    $this.closest('.rating').find('.stars_current').data('rating', currentStarWidth);
    if ($this.closest('.input').find('input[name=RATING]').length) {
        $this.closest('.input').find('input[name=RATING]').val(ratingValue)
    } else {
        $this.closest('.input').find('input[data-sid=RATING]').val(ratingValue)
    }
    $this.closest('.rating_wrap').find('.rating_message').data('message', ratingMessage)
});
$(document).on('click', '#submitReview', function() {
    var name = $('#Name').val();
    var text = $('#ReviewContent').val();
    var rate = $('#rRating').val();
    var my_image_upload = $('#my_image_upload').val();
    if (name == '') {
        $('#Name').addClass('wpcf7-not-valid');
        $('.name-field').addClass('d-block');
    } else {
        $('#Name').removeClass('wpcf7-not-valid');
        $('.name-field').removeClass('d-block');
    }

    if (text == '') {
        $('#ReviewContent').addClass('wpcf7-not-valid');
        $('.name-field2').addClass('d-block');
    } else {
        $('#ReviewContent').removeClass('wpcf7-not-valid');
        $('.name-field2').removeClass('d-block');
    }

    if (name !== '' && text !== '') {
        $.ajax({
            url: '/wp-content/themes/kids/ajaxupload.php',
            type: 'POST',
            data: new FormData(document.getElementById("featured_upload")),
            contentType: false,
            cache: false,
            processData: false,
            success: function(data) {
                $('.result').text('Спасибо! Ваш отзыв отправлен на модерацию.');
                $('#submitReview').attr('disabled', true);
            }
        })
    }
});

Здесь сразу и события на звездочки рейтинга и отправка самой формы в обработчик ajaxopload.php

Шаг 5. Обработчик ajaxopload.php

<?php

$parse_uri = explode( 'wp-content', $_SERVER['SCRIPT_FILENAME'] );
require_once( $parse_uri[0] . 'wp-load.php' );

 $post_title = $_POST['name'];
 $post_content = $_POST['text'];
 $rate = $_POST['rate'];
 $town = $_POST['town'];

 $new_post = array(
'post_type' => 'testimonials',
 'post_content' => $post_content,
 'post_title' => $post_title,
 'post_status' => 'pending',
 );

 $post_id = wp_insert_post($new_post);


if (
	isset( $_POST['my_image_upload_nonce'], $post_id )
	&& wp_verify_nonce( $_POST['my_image_upload_nonce'], 'my_image_upload' )
) {
	// все ок! Продолжаем.
	// Эти файлы должны быть подключены в лицевой части (фронт-энде).
	require_once( ABSPATH . 'wp-admin/includes/image.php' );
	require_once( ABSPATH . 'wp-admin/includes/file.php' );
	require_once( ABSPATH . 'wp-admin/includes/media.php' );

	// Позволим WordPress перехватить загрузку.
	// не забываем указать атрибут name поля input - 'my_image_upload'
	$attachment_id = media_handle_upload( 'my_image_upload', $post_id );

	if ( is_wp_error( $attachment_id ) ) {
		echo "Ошибка загрузки медиафайла.";
	} else {
		echo "Медиафайл был успешно загружен!";
	}

} else {
	echo "Проверка не пройдена. Невозможно загрузить файл.";
}

if( set_post_thumbnail($post_id, $attachment_id) )
	echo 'Миниатюра установлена.';
else
	echo 'Миниатюра удалена.';

update_field('rating', $rate, $post_id );

update_field('town', $town, $post_id );

$to  = "почтаадмина@mail.ru";

$subject = "Новый отзыв ожидает вашей проверки";

$message = ' <p>Имя '.$post_title.'</p> </br> Текст отзыва: </br> '.$post_content.' ';

$headers  = "Content-type: text/html; charset=utf-8 \r\n";
$headers .= "From: <info@вашадоменнаяпочта.ru>\r\n";

mail($to, $subject, $message, $headers);

?>

Этот скрипт создает запись в нашем post_type и отправляет данные на почту.

Шаг 6. Причесываем CSS

.rr_review_name {
  color: #f68315;
  font-family: MontserratBold;
  font-size: 15px;
  font-weight: 700;
  line-height: 21px;
}

.text p {
  color: #717171;
  font-size: 16px;
  line-height: 24px;
  margin-top: 25px;
  font-family: 'MontserratItalic';
  max-width: 80%;
}

.stars_current {
  width: 80%;
  font-size: 0;
  margin-top: 5px;
  display: block;
  color: #e3c45a;
  letter-spacing: 3px;
}

.add_review button {
  width: 225px;
  height: 50px;
  background-color: #613085;
  background-image: none;
  font-size: 14px;
  margin-bottom: 30px;
}

.add_review {
  margin-top: 85px;
}

#exampleModalCenter3 .modal-dialog {
  max-width: 400px;
}

.rr_review_form input {
  color: #717171;
  font-size: 14px;
  font-weight: 400;
  line-height: 24px;
  padding-left: 26px;
  overflow: visible;
  width: 100%;
  height: 50px;
  border: 1px solid #c3c3c3;
  border-radius: 30px;
  background-color: transparent;
}

.rr_review_form textarea {
  color: #717171;
  font-size: 14px;
  font-weight: 400;
  line-height: 24px;
  padding-left: 26px;
  overflow-y: auto !important;
  width: 100%;
  height: 155px;
  border: 1px solid #c3c3c3;
  border-radius: 30px;
  background-color: transparent;
  margin-right: 0;
  max-width: 100%;
}

.form-control:focus {
  color: #495057;
  background-color: #fff;
  border-color: #613085;
  outline: 0;
  box-shadow: 0 0 0 0.2rem rgba(97, 48, 133, 0.25);
}

form .row[data-sid=RATING] .rating {
  /* float: left; */
  position: relative;
  width: 150px;
  height: 24px;
  font-size: 0;
  line-height: 0;
  background: url(../img/bigstars.svg) 0 -26px no-repeat;
  margin-right: 8px;
  margin-top: -2px;
  display: flex;
  display: inline-block;
}

form .row[data-sid=RATING] .rating .star {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 0;
  height: 24px;
  display: inline-block;
  width: 20%;
  background: none;
  cursor: pointer;
  border-radius: 0;
}

.stars, .rr_star {
  color: #ffaf00;
}

.rating .stars_current {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  display: block;
  width: 0;
  background: url(../img/bigstars.svg) 0 0 no-repeat;
  margin: 0;
}

.rating_message {
  display: inline-block;
  position: relative;
  top: -5px;
}

.item-views.reviews_items .items .item .rating_wrap {
  margin: 0;
  display: inline-block;
  vertical-align: top;
  margin-top: 15px;
}

.rating {
  position: relative;
  width: 121px;
  height: 19px;
  font-size: 0;
  line-height: 0;
  background: url(../img/stars.svg) 0 -21px no-repeat;
}

.stars .rating .stars_current {
  background: url(../img/stars.svg) 0 0 no-repeat;
}

.rr_review_form .row {
  color: #717171;
  font-size: 14px;
}

Я в тупую скопировал стили с сайта примера. Поэтому редактируйте их сами. Самое важное что здесь нужно это stars.svg и bigstars.svg без них у вас тупо не будут отображаться звездочки.

starsСкачать
bigstarsСкачать

Шаг 7. Вывод комментариев

<div class="add_review">
            <div class="button add_review_icon">
              <button class="btn btn-default btn-lg animate-load" data-toggle="modal" data-target="#exampleModalCenter3">Оставить свой отзыв</button>
            </div>
          </div>
          <div class="item-views reviews_items">
            <div class="group-content">
              <div class="sid- items">
                <?php
                $args = array(
                'post_type' => 'testimonials',
                'publish' => true,
                );
                query_posts($args);?>
                <div class="testimonial_group">
                  <?php if (have_posts()) : ?>
                  <?php while (have_posts()) : the_post(); ?>
                  <div class="col-md-12 item question1" itemscope="" itemtype="http://schema.org/Review">

                    <div class="d-flex">
                      <div class="photo" style="background-image:url('<?php the_post_thumbnail_url('medium'); ?>');"></div>
                      <div class="">
                      <span itemprop="itemReviewed" itemscope="" itemtype="http://schema.org/Product">
                        <div class="rr_review_post_id" itemprop="name" style="display:none;">
                          <a href="https://kidsprofiki.com/otzyvy/" tabindex="-1">
                          Отзывы
                        </a>
                        </div>
                      </span>
                    <span class="rr_date" style="display:none;"><meta itemprop="datePublished" content="2019-02-27 14:04:04">
                      <time datetime="">
                      </time>
                    </span>
                    <div class="rr_review_name" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
                      <span itemprop="name"><?php the_title(); ?>	</span>
                    </div>
                    <span class="townn">г. <?php the_field('town'); ?></span>
                    <div class="top-wrapper">
                      <div class="rating_wrap">
                        <div class="stars">
                          <div class="rating current_5">
                            <span class="stars_current" style="<?php
                              $rate = get_field('rating');
                              switch ($rate) {
                              case 0:
                              echo "width: 0%;";
                              break;
                              case 1:
                              echo "width: 20%;";
                              break;
                              case 2:
                              echo "width: 40%;";
                              break;
                              case 3:
                              echo "width: 60%;";
                              break;
                              case 4:
                              echo "width: 80%;";
                              break;
                              case 5:
                              echo "width: 100%;";
                              break;
                              }
                            ?>">
                              <?php
                                for($i=1;$i<=$rate;$i++)
                                {
                                print '★';
                                }
                              ?>
                            </span>
                          </div>
                        </div>
                      </div>
                    </div>
                    <div style="display:none;" itemprop="reviewRating" itemscope="" itemtype="http://schema.org/Rating">
                      <span itemprop="ratingValue">
                        5
                      </span>
                      <span itemprop="bestRating">
                        5
                      </span>
                      <span itemprop="worstRating">
                        1
                      </span>
                    </div>
                    <div class="text"><span itemprop="reviewBody"><?php the_content(); ?></span></div>
                    </div>
                    </div>
                    </div>
                    <?php endwhile; ?>
                    <?php endif; ?>
                  </div>
                </div>
              </div>
        </div>

Опять же, просто скопировал свою верстку. Стилизуйте и смотрите сами как вам надо.

Рабочий пример на сайте клиента: https://kidsprofiki.com/otzyvy/

Забыл сказать, что отзыв отправляется на модерацию и его надо еще опубликовать, чтоб он появился.

P.S. Я не претендую на лавры крутого программиста. Да, можно по-другому. Да, можно проще. Но я делюсь с вами своим решением. Возможно когда-то я все это переделаю. А пока, можете сами под себя переделывать сколько угодно )

Ajax подгрузка постов в WordPress. Или бесконечная прокрутка

13 октября, 2018

Что мы попробуем сделать в этом посту?

Шаг 1. Добавление кнопки «Загрузить ещё» 

Для начала нам надо найти файл, в котором добавляется постраничная навигация. В TwentySeventeen этот файл — прямо index.php.

Если же вы решили использовать какую-то из стандартных тем (как я), то напоминаю, что для изменений желательно использовать дочерние темы (подробнее на видео в самом низу поста).

Найдите соответствующее место в шаблоне за пределами цикла while, то есть после того, как заканчивается вывод постов (в TwentySeventeen это место практически сразу после endwhile) и вставляем туда код:

<?php if (  $wp_query->max_num_pages > 1 ) : ?>
	<script>
	var ajaxurl = '<?php echo site_url() ?>/wp-admin/admin-ajax.php';
	var true_posts = '<?php echo serialize($wp_query->query_vars); ?>';
	var current_page = <?php echo (get_query_var('paged')) ? get_query_var('paged') : 1; ?>;
	var max_pages = '<?php echo $wp_query->max_num_pages; ?>';
	</script>
	<div id="true_loadmore">Загрузить ещё</div>
<?php endif; ?>
ajaxurl
Это обработчик AJAX-запросов в WordPress.
true_posts
Сериализованный массив, содержащий все необходимые параметры запроса, является свойством класса WP_Query.
current_page
Номер текущей страницы.

А теперь немного стилей, которые мы добавим на нашу кнопку, чтобы она круто выглядела (стили можно вставить в стандартный style.css в папке с темой).

#true_loadmore{
	background-color: #ddd; /* сервый фон */
    	border-radius: 2px; /* закругление углов */
    	display: block; /* блочный элемент, на случай, если захотите использовать <a> */
    	text-align: center; /* выравнивание текста по центру */
    	font-size: 14px; font-size: 0.875rem; /* размер шрифта */
    	font-weight: 800; /* начертание */
    	letter-spacing: 1px; /* межбуквенный интервал */
    	cursor: pointer; /* курсор мыши при наведении такой же, как при наведении на ссылку */
    	text-transform: uppercase;
    	padding: 10px 0; /* внутренние отступы сверху и снизу у кнопки */
    	transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out, color 0.3s ease-in-out; /* CSS-анимация*/
}
#true_loadmore:hover{
	background-color: #767676;
	color: #fff;
}

Успешным выполнением первого шага будет считаться вот такая кнопка, которая должна будет появиться на странице всех ваших записей, но имейте ввиду, что если записей недостаточно для двух страниц, то кнопки не будет, для этого либо создайте больше записей, либо перейдите в Настройки > Чтение и измените количество отображаемых на странице записей там.

Кнопка асинхронной бесконечной загрузки постов

Самый легкий шаг позади.

Шаг 2. Подключение скриптов jQuery 

Документация функций wp_enqueue_script() и get_stylesheet_directory_uri() в помощь. Про подключение скриптов я писал часто и подробно, поэтому сейчас на этом останавливаться не будем, если есть проблемы — смотрите документацию. А этот код — в functions.php.

function true_loadmore_scripts() {
	wp_enqueue_script('jquery'); // скорее всего он уже будет подключен, это на всякий случай
 	wp_enqueue_script( 'true_loadmore', get_stylesheet_directory_uri() . '/loadmore.js', array('jquery') );
}
 
add_action( 'wp_enqueue_scripts', 'true_loadmore_scripts' );

Шаг 3. Скрипт асинхронной загрузки 

Вы ещё не создали файл loadmore.js в папке с темой? Давайте создадим его и добавим туда следующий код:

jQuery(function($){
	$('#true_loadmore').click(function(){
		$(this).text('Загружаю...'); // изменяем текст кнопки, вы также можете добавить прелоадер
		var data = {
			'action': 'loadmore',
			'query': true_posts,
			'page' : current_page
		};
		$.ajax({
			url:ajaxurl, // обработчик
			data:data, // данные
			type:'POST', // тип запроса
			success:function(data){
				if( data ) { 
					$('#true_loadmore').text('Загрузить ещё').before(data); // вставляем новые посты
					current_page++; // увеличиваем номер страницы на единицу
					if (current_page == max_pages) $("#true_loadmore").remove(); // если последняя страница, удаляем кнопку
				} else {
					$('#true_loadmore').remove(); // если мы дошли до последней страницы постов, скроем кнопку
				}
			}
		});
	});
});

Я постарался сделать этот код максимально простым, дополнительными переменными усложнять его не стал. Если вы хотя бы немного разбираетесь в jQuery, то у вас не возникнет с ним никаких проблем. Даже если не разбираетесь, но сделаете всё по инструкции, то всё тоже будет ок.

Шаг 4. Обработчик PHP, вывод постов 

Этот код также отправляется в файл functions.php. Если он вам непонятен, читайте подробнее про WP_Query и query_posts().

<?php
function true_load_posts(){
 
	$args = unserialize( stripslashes( $_POST['query'] ) );
	$args['paged'] = $_POST['page'] + 1; // следующая страница
	$args['post_status'] = 'publish';
 
	// обычно лучше использовать WP_Query, но не здесь
	query_posts( $args );
	// если посты есть
	if( have_posts() ) :
 
		// запускаем цикл
		while( have_posts() ): the_post();
 
			get_template_part( 'template-parts/post/content', get_post_format() );
 
		endwhile;
 
	endif;
	die();
}
 
 
add_action('wp_ajax_loadmore', 'true_load_posts');
add_action('wp_ajax_nopriv_loadmore', 'true_load_posts');

Бесконечная загрузка постов при прокрутке страницы. 

Суть в том, что вы просто скроллите страницу вниз, а новые посты подгружаются по мере её прокрутки. Насколько я помню, впервые такая штука появилась у твиттера (могу ошибаться, поправьте, если я не прав), а потом уже все стянули её оттуда.

Скажу честно — заразная вещь. Те, кто сидят на сайте вконтакте, понимают это прекрасно. Так что, если у вас новостной сайт, тогда этот способ загрузки постов просто «must have».

Если вы сделали все предыдущие шаги из поста и дошли до этого момента — тогда отлично, добавим некоторые изменения для шагов 1 и 3.

Во-первых, кнопка Загрузить ещё нам больше не понадобится, поэтому немного изменим HTML-код:

<?php if (  $wp_query->max_num_pages > 1 ) : ?>
	<script id="true_loadmore">
	var ajaxurl = '<?php echo site_url() ?>/wp-admin/admin-ajax.php';
	var true_posts = '<?php echo serialize($wp_query->query_vars); ?>';
	var current_page = <?php echo (get_query_var('paged')) ? get_query_var('paged') : 1; ?>;
	</script>
<?php endif; ?>

Во-вторых, стили CSS нам тоже больше не нужны, если вы их добавляли, можете напрочь удалить.

В-третьих, содержимое файла loadmore.js изменится и будет следующим:

jQuery(function($){
	$(window).scroll(function(){
		var bottomOffset = 2000; // отступ от нижней границы сайта, до которого должен доскроллить пользователь, чтобы подгрузились новые посты
		var data = {
			'action': 'loadmore',
			'query': true_posts,
			'page' : current_page
		};
		if( $(document).scrollTop() > ($(document).height() - bottomOffset) && !$('body').hasClass('loading')){
			$.ajax({
				url:ajaxurl,
				data:data,
				type:'POST',
				beforeSend: function( xhr){
					$('body').addClass('loading');
				},
				success:function(data){
					if( data ) { 
						$('#true_loadmore').before(data);
						$('body').removeClass('loading');
						current_page++;
					}
				}
			});
		}
	});
});

Файл functions.php (это шаги 2 и 4) мы оставляем без изменений.