javbus.waterfall

Infinite scroll @ javbus.com

Verzia zo dňa 04.06.2017. Pozri najnovšiu verziu.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name        javbus.waterfall
// @description Infinite scroll @ javbus.com
// @namespace   https://github.com/FlandreDaisuki
// @include     https://www.javbus.com/*
// @include     https://www.javbus2.com/*
// @include     https://www.javbus3.com/*
// @include     https://www.javbus5.com/*
// @include     https://www.javbus.me/*
// @version     2017.06.04
// @grant       none
// ==/UserScript==
const $ = jQuery;

class Lock {
  constructor(d = false) {
    this.locked = d;
  }
  lock() {
    this.locked = true;
  }
  unlock() {
    this.locked = false;
  }
}

class Waterfall {
  constructor(selectorcfg = {}) {
    this.lock = new Lock();
    this.baseURI = this.getBaseURI();
    this.selector = {
      next: 'a.next',
      item: '',
      cont: '', //container
      pagi: '.pagination',
    };
    Object.assign(this.selector, selectorcfg);
    this.pagegen = this.fetchSync(location.href);
    this.anchor = $(this.selector.pagi)[0];
    this._count = 0;
    this._1func = function(cont, elems) {
      cont.empty().append(elems);
    };
    this._2func = function(cont, elems) {
      cont.append(elems);
    };

    if ($(this.selector.item).length) {
      document.addEventListener('scroll', this.scroll.bind(this));
      document.addEventListener('wheel', this.wheel.bind(this));
      this.appendElems(this._1func);
    }
  }

  getBaseURI() {
    let _ = location;
    return `${_.protocol}//${_.hostname}${(_.port && `:${_.port}`)}`;
  }

  getNextURL(href) {
    let a = document.createElement('a');
    a.href = href;
    return `${this.baseURI}${a.pathname}${a.search}`;
  }

  fetchURL(url) {
    console.log(`fetchUrl = ${url}`);
    const fetchwithcookie = fetch(url, { credentials: 'same-origin' });
    return fetchwithcookie
      .then(response => response.text())
      .then(html => new DOMParser().parseFromString(html, 'text/html'))
      .then(doc => {
        let $doc = $(doc);
        let href = $doc.find(this.selector.next).attr('href');
        let nextURL = href ? this.getNextURL(href) : undefined;
        let elems = $doc.find(this.selector.item);

        return {
          nextURL,
          elems
        };
      });
  }

  *fetchSync(urli) {
    let url = urli;
    do {
      yield new Promise((resolve, reject) => {
        if (this.lock.locked) {
          reject();
        } else {
            this.lock.lock();
          resolve();
        }
      }).then(() => {
          return this.fetchURL(url)
          .then(info => {
            url = info.nextURL;
            return info.elems;
          });
      }).then(elems => {
        this.lock.unlock();
        return elems;
      }).catch((err) => {
        // Locked!
      });
    } while (url);
  }

  appendElems() {
    let nextpage = this.pagegen.next();
    if (!nextpage.done) {
        nextpage.value.then(elems => {
          const cb = (this._count === 0) ? this._1func : this._2func;
          cb($(this.selector.cont), elems);
          this._count += 1;
        });
    }
    return nextpage.done;
  }

  end() {
    console.info('The End');
    document.removeEventListener('scroll', this.scroll.bind(this));
    document.removeEventListener('wheel', this.wheel.bind(this));
    $(this.anchor).replaceWith($(`<h1>The End</h1>`));
  } 

  static reachBottom(elem, limit) {
    return (elem.getBoundingClientRect().top - $(window).height()) < limit;
  }
  
  scroll() {
    if (Waterfall.reachBottom(this.anchor, 500) && this.appendElems(this._2func)) {
      this.end();
    }
  }

  wheel() {
    if (Waterfall.reachBottom(this.anchor, 1000) && this.appendElems(this._2func)) {
      this.end();
    }
  }

  setFirstCallback(f) {
    this._1func = f;
  }

  setSecondCallback(f) {
    this._2func = f;
  }
}

const w = new Waterfall({
  next: 'a#next',
  item: '.item',
  cont: '#waterfall',
});

w.setSecondCallback(function(cont, elems) {
  if(location.pathname.includes('/star/')) {
    cont.append(elems.slice(1));
  } else {
    cont.append(elems);
  }
});

function addStyle(styleStr) {
  $('head').append(`<style>${styleStr}</style>`);
}

addStyle(`
  #waterfall {
    height: initial !important;
    width: initial !important;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
  }
  #waterfall .item.item {
    position: relative !important;
    top: initial !important;
    left: initial !important;
    float: none;
    flex: 25%;
  }
  #waterfall .movie-box,
  #waterfall .avatar-box {
    width: initial !important;
    display: flex;
  }
  #waterfall .movie-box .photo-frame {
    overflow: visible;
  }`);