Googleが推奨する「戻るボタン対応・SEO」の無限スクロールを使ってみた

無限スクロール、いいですよね。
ところが巷に配布されているプラグインの多くは、ブラウザのバックボタンで戻ったら最初から読み込み直しでヴァー、ということがあってユーザビリティ上よろしくないのです。

Google先生が対応策としてサンプルのJavascriptをつくってくれたので、いろんな案件で使えるようにちょっと手を入れてみました。

元にしたのはこちらのサンプルです。
http://scrollsample.appspot.com/items

解説は下記ブログ記事をご覧ください。
Googleが推奨するSEOに適した無限スクロールの構成方法

  • あらかじめページを分割しておく。いわゆるページネーション
  • 分割されたページのうち1つを表示(1ページ目でなくても見られるようにする)
  • その上下に前のページ、次のページをAjaxで読み込んでいく
  • 今表示している部分が何ページ目に相当するかに合わせて、URLを動的に書き換える

自分なりに書き換えてみたソースは下記です。jQueryを読み込んだ後に実行してください。


$(function (){
//infinite scroll
var prev_data_selector = '.prev.page-numbers'; //「前へ」リンクのaタグのセレクタ
var next_data_selector = '.next.page-numbers'; //「次へ」リンクのaタグのセレクタ
var itemWrapperSelector = '.list_infinite'; //無限ローディングのwrapperとなるタグのセレクタ
var itemWrapper = $(itemWrapperSelector);
var itemInnerSelector = '.list_infinite_item'; //無限ローディングの本体(本文)となるタグのセレクタ
var itemPagerSelector = '.pagination'; //ページャーのセレクタ
var itemPager = $(itemPagerSelector);
var prev_data_url;
var next_data_url;
var next_data_cache;
var prev_data_cache;
var last_scroll = 0;
var is_loading = 0;

if(itemWrapper[0]) {
	prev_data_url = $(prev_data_selector).attr('href');
	next_data_url = $(next_data_selector).attr('href');
	fadeInItem(true);
	initPaginator();
	loadPrevious();
    // if we have enough room, load the next batch
    if ($(window).height()>itemWrapper.height()) {
      if (next_data_url!== '') {
        loadFollowing();
      } 
    }
}

function initPaginator() {
	$(document).off( 'scroll');
  $(document).on( 'scroll', function(){
    // handle scroll events to update content
    var scroll_pos = $(window).scrollTop();
    if (scroll_pos >= 0.9*($(document).height() - $(window).height())) {
      if (is_loading===0) {
		  loadFollowing();
	  }
    }
    if (scroll_pos <= 0) {
      if (is_loading===0) {
		  loadPrevious();
	  }
    }
    // Adjust the URL based on the top item shown
    // for reasonable amounts of items
    if (Math.abs(scroll_pos - last_scroll)>$(window).height()*0.1) {
      last_scroll = scroll_pos;
      $(itemInnerSelector).each(function() {
        if (mostlyVisible(this)) {
          history.replaceState(null, null, $(this).attr('data-url'));
          return(false);
        }
      });
    }
  });
}


function loadFollowing() {
  if (next_data_url){
    is_loading = 1; // note: this will break when the server doesn't respond
    itemPager.hide();
    if (next_data_cache) {
      showFollowing(next_data_cache);
      is_loading = 0;
    } else {
		$.ajax({
			url: next_data_url,
			type: 'get',
			dataType: 'html',
		}).success(function(data){
	        showFollowing(data);
   		     is_loading = 0;
		});
    }
  }
}
    function showFollowing(data) {
	var out_html = $($.parseHTML(data));
      itemWrapper.append(out_html.find(itemWrapperSelector).filter(itemWrapperSelector)[0].innerHTML);
	  initPaginator();
      next_data_url = out_html.find(next_data_selector).filter(next_data_selector).attr('href');
      next_data_cache = false;
		$.ajax({
			url: next_data_url,
			type: 'get',
			dataType: 'html',
		}).success(function(preview_data){
	        next_data_cache = preview_data;
		});
    }

function loadPrevious() {
  if (prev_data_url){
    is_loading = 1; // note: this will break when the server doesn't respond
    itemPager.hide();
    if (prev_data_cache) {
      showPrevious(prev_data_cache);
      is_loading = 0;
    } else {
		$.ajax({
			url: prev_data_url,
			type: 'get',
			dataType: 'html',
		}).success(function(data){
	        showPrevious(data);
   		     is_loading = 0;
		});
    }
  }
}
    function showPrevious(data) {
	var out_html = $($.parseHTML(data));
      itemWrapper.prepend(out_html.find(itemWrapperSelector).filter(itemWrapperSelector)[0].innerHTML);
	  initPaginator();
      var item_height = $(itemInnerSelector + ':first').height();
      window.scrollTo(0, $(window).scrollTop()+item_height); // adjust scroll
	  prev_data_url = out_html.find(prev_data_selector).filter(prev_data_selector).attr('href');
      prev_data_cache = false;
		$.ajax({
			url: prev_data_url,
			type: 'get',
			dataType: 'html',
		}).success(function(preview_data){
	        prev_data_cache = preview_data;
		});
    }

function mostlyVisible(element) {
  var scroll_pos = $(window).scrollTop();
  var window_height = $(window).height();
  var el_top = $(element).offset().top;
  var el_height = $(element).height();
  var el_bottom = el_top + el_height;
  return ((el_bottom - el_height*0.25 > scroll_pos) && 
          (el_top < (scroll_pos+0.5*window_height)));
}


});

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA