tzkmx
1/17/2018 - 11:40 PM

A jQuery UI widget to navigate through WP posts

A jQuery UI widget to navigate through WP posts

(function ($) {
  $.widget('tzk.postsnavigator', {
    options: {
      page: 1,
      per_page: 4,
      base: location.origin + '/wp-json/wp/v2/posts/',
      totalPosts: false
    },
    _create: function () {
      this.element.addClass('tzk-postsnavigator ui-widget')
      this.element.find('ul').addClass('ui-widget-content')

      this.renderList()
      this._on(this.element, {
        'click .load-more': this.next,
        'click .go-back': this.prev
      })
    },

    next: function () {
      var elemsLength = this.element.find('li').length

      var nextPage = this.options.page + 1

      if ((!this.options.totalPosts) ||
                (elemsLength < this.options.totalPosts)
            ) {
        this.loadMorePosts(nextPage)
      }
      this._advancePage(nextPage)
    },

    prev: function () {
      var page = this.options.page - 1
      if (page >= 1) {
        this.option('page', page)
      }
    },

    _setOption (key, value) {
      this._super(key, value)
      if (key === 'page') {
        this.renderList(true)
      } else {
        this.renderList()
      }
    },

    renderList: function (change = false) {
      var upto = this.options.per_page * this.options.page
      var from = this.options.per_page * (this.options.page - 1)
      var list = this.element.find('li')
      list.each(function (idx, elem) {
        if (idx >= from && idx < upto) {
          $(elem).show()
        } else {
          $(elem).hide()
        }
      })
      if (change) {
        $('html, body').animate({
          scrollTop: $(this.element).offset().top
        }, 1600)
      }

      this.element.find('.controls').remove()
      var controls = $('<div>').attr('class', 'controls')
      if (this.options.page > 1) {
        controls.append('<div class="button go-back">Regresar</div>')
      }
      var maxshown = this.options.per_page * this.options.page
      var shown = this.element.find('li').length
      var loadmore = '<div class="button load-more">Cargar más</div>'
      if ((this.options.page === 1 && shown > 4) ||
            (this.options.totalPosts > shown) ||
            (this.options.totalPosts > maxshown)
            ) {
        controls.append(loadmore)
      }
      this.element.find('ul').after(controls)
    },

    loadMorePosts: function (askedPage) {
      var endpoint = this.options.base
      var container = this.element.find('ul')
      var args = container.data()
      args._embed = true
      var totalPosts = this.options.totalPosts

      if (totalPosts && args.offset >= totalPosts) {
                /* console.log('not asking more, reached end'); */
        return
      }
      var self = this
      $.getJSON(endpoint, args, function (posts, text, jqXHR) {
        var offset = container.data('offset')
        var total = jqXHR.getResponseHeader('x-wp-total')
        if (total) {
          self.option('totalPosts', total)
        }
        $.each(posts, function (idx, post) {
          var title = post.title.rendered
          var media = post._embedded['wp:featuredmedia'][0]
          var alt = media.alt_text
          var big = media.media_details.sizes.full
          var small = media.media_details.sizes.medium
          var insertPost = "<li style='display:none' class='contrib-post'>" +
                        "<div class='post-thumbnail'><a href='" + post.link + "'>" +
                        "<img src='" + small.source_url + "' " + "alt='" + alt + "' " +
                        "class='attachment-tie-large size-tie-large wp-post-image' " +
                        "srcset='" + big.source_url + ' ' + big.width + 'w, ' +
                        small.source_url + ' ' + small.width + "w'/></a></div>" +
                        "<h3><a style='width:97.5%;' href='" + post.link + "'>" + title + '</a></h3></li>'
          container
                        .data('offset', ++offset)
                        .append(insertPost)
        })
        if (this.options.page !== askedPage) {
          self._advancePage(askedPage)
        } else {
          this.renderList()
        }
      })
    },

    _advancePage: function (askedPage) {
      if (!this.options.totalPosts) {
        this.option('page', askedPage)
        return
      }
      if ((this.options.page * this.options.per_page) < this.element.find('li').length) {
        this.option('page', askedPage)
      }
    }
  })
})(jQuery)

As seen on:

https://elsemanario.com/colaboradores/manuel-ramiro-hernandez/244451/una-lectura-casi-imprescindible/

You can use it like this:

$('.widget.category-posts').postsnavigator()