Craeckerffm
7/14/2017 - 10:58 AM

source.js

source.js

import 'promise-polyfill';
import 'whatwg-fetch';

if (!window.Promise) {
  window.Promise = Promise;
}


export default class Ajaxload {
  constructor(link, wrapper, options) {
    this.link = document.querySelectorAll(link);
    this.wrapper = document.querySelector(wrapper);
    this.config = {
      ajaxContent: '.js-content',
      animationOut: 200,
      animationIn: 200,
      prefetch: false,
      gsap: false,
      headers: {
        'X-Requested-With': 'XMLHttpRequest'
      }
    };
    Object.assign(this.config, options);
    this.init();
  }
  init() {
    Array.from(this.link).forEach(link => {
      link.addEventListener('mouseover', e => this.fetchData(e));
      link.addEventListener('click', e => this.isSessionReady(e));
    });
    window.addEventListener('popstate', () => {
      const initPageJSON = sessionStorage.getItem('initPage');
      const initPage = JSON.parse(initPageJSON);
      event.state === null ? this.switchContent(initPage.title, initPage.content) : this.changeState();
    });
    document.addEventListener('DOMContentLoaded', () => {
      sessionStorage.setItem('initPage', JSON.stringify({
        content: this.wrapper.innerHTML,
        title: document.title,
      }));
    });
  }
  fetchData(e) {
    if ((e.target.dataset.ajaxnavprefetch === 'disabled') || (!this.config.prefetch === true)) return false;
    const url = e.target.href;
    if (sessionStorage.getItem(url) === null) {
      fetch(url, {
        headers: new Headers(this.config.headers),
      })
        .then((response) => {
          if (!response.ok) {
            throw Error(response.statusText);
          }
          return response;
        })
        .then(response => response.text())
        .then(content => sessionStorage.setItem(url, JSON.stringify(content)))
        .catch(error => console.log(error));
    }
  }
  isSessionReady(e) {
    e.preventDefault();
    if (e.target.href === document.location.href) return false;
      const source = e.target.href;
      const content = sessionStorage.getItem(source);
      sessionStorage[source] ? this.prepareContent(e, content) : this.refetchData(e, source);
  }
  prepareContent(e, content) {
    let newDiv;
    this.isJson(content) ? newDiv = JSON.parse(content) : newDiv = content;
    if (this.config.gsap === false) {
      return new Promise((resolve, reject) => {
          this.fadeOut(this.wrapper, this.config.animationOut, () => resolve());
        }).then(() => {
          this.wrapper.firstChild.remove();
          this.wrapper.innerHTML = newDiv;
          this.setTitle();
          this.setHistory(e, newDiv);
        }).then(() => this.fadeIn(this.wrapper, this.config.animationIn))
        .catch(error => console.warn(error));
    } else {
      console.log('gsap');
    }
  }
  refetchData(e, source) {
    fetch(source, {
      headers: new Headers(this.config.headers),
      })
      .then((response) => {
        if (!response.ok) {
          throw Error(response.statusText);
        }
        return response;
      })
      .then(response => response.text())
      .then(content => this.prepareContent(e, content))
      .then(() => console.log('loaded fresh'))
      .catch(error => console.log(error));
  }
  setHistory(e, newDiv) {
    const stateObj = {
      content: {
        content: newDiv,
        title: document.title,
      },
      url: e.target.href,
    };
    window.history.pushState(stateObj.content, '', stateObj.url);
  }
  changeState() {
    if (event.state) {
      const state = {
        content: event.state.content,
        title: event.state.title,
      };
      this.switchContent(state.title, state.content);
    }
  }
  switchContent(title, content) {
    if (this.config.gsap === false) {
      return new Promise((resolve, reject) => {
        this.fadeOut(this.wrapper, this.config.animationOut, () => resolve());
      }).then(() => {
        this.wrapper.firstChild.remove();
        this.wrapper.innerHTML = content;
        document.title = title;
      }).then(() => this.fadeIn(this.wrapper, this.config.animationIn));
    } else {
    console.log('gsap');
    }
  }
    //Helper
  fadeOut(el, duration, cb) {
    let s = el.style;
    let step = 25 / (duration || 300);
    s.opacity = s.opacity || 1;

    (function fade() {
      if ((s.opacity -= step) < 0) {
        s.display = "block";
        return cb();
      }
      return setTimeout(fade, 25);
    })();
  }
  fadeIn(el, duration, display) {
    let s = el.style,
      step = 25 / (duration || 300);
    s.opacity = s.opacity || 0;
    s.display = display || "block";
    (function fade() {
      (s.opacity = parseFloat(s.opacity) + step) > 1 ? s.opacity = 1 : setTimeout(fade, 25);
    })();
  }
  setTitle() {
    if (document.querySelector(this.config.ajaxContent) === null) {
      throw Error('Please check your ajaxContent Class');
      return false;
    }
    const title = document.querySelector(this.config.ajaxContent).dataset.ajaxnavtitle;
    document.title = title;
  }
  isJson(str) {
    try {
      JSON.parse(str);
    } catch (e) {
      return false;
    }
    return true;
  }
}