335 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			335 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
 | 
						|
window.requestAnimFrame = (function(){
 | 
						|
  return window.requestAnimationFrame
 | 
						|
          || window.webkitRequestAnimationFrame
 | 
						|
          || window.mozRequestAnimationFrame
 | 
						|
          || function(callback) { window.setTimeout(callback, 1000 / 60);};
 | 
						|
})();
 | 
						|
 | 
						|
(() => {
 | 
						|
  let video;
 | 
						|
  if(elem = document.querySelector("#my-video")) {
 | 
						|
    video = new v0ck(elem);
 | 
						|
    document.addEventListener("keydown", e => {
 | 
						|
      if(e.key === " " && e.target.tagName !== "INPUT" &&  e.target.tagName !== "TEXTAREA") {
 | 
						|
        video[video.paused ? 'play' : 'pause']();
 | 
						|
        document.querySelector('.v0ck_overlay').classList[video.paused ? 'remove' : 'add']('v0ck_hidden');
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    document.getElementById('togglebg').addEventListener('click', function (e) {
 | 
						|
      e.preventDefault();
 | 
						|
      background = !background;
 | 
						|
      localStorage.setItem('background', background.toString());
 | 
						|
      var canvas = document.getElementById('bg');
 | 
						|
      if (background) {
 | 
						|
          canvas.classList.add('fader-in');
 | 
						|
          canvas.classList.remove('fader-out');
 | 
						|
      } else {
 | 
						|
          canvas.classList.add('fader-out');
 | 
						|
          canvas.classList.remove('fader-in');
 | 
						|
      }
 | 
						|
      animationLoop();
 | 
						|
    });
 | 
						|
 | 
						|
  if(elem !== null) {
 | 
						|
    if(localStorage.getItem('background') == undefined) {
 | 
						|
      localStorage.setItem('background', 'true');
 | 
						|
    }
 | 
						|
    
 | 
						|
    var background = localStorage.getItem('background') === 'true';
 | 
						|
    var canvas = document.getElementById('bg');
 | 
						|
    var context = canvas.getContext('2d');
 | 
						|
    var cw = canvas.width = canvas.clientWidth | 0;
 | 
						|
    var ch = canvas.height = canvas.clientHeight | 0;
 | 
						|
 | 
						|
    function animationLoop() {
 | 
						|
      if(video.paused || video.ended || !background)
 | 
						|
          return;
 | 
						|
      context.drawImage(video, 0, 0, cw, ch);
 | 
						|
      window.requestAnimFrame(animationLoop);
 | 
						|
  }
 | 
						|
 | 
						|
    elem.addEventListener('play', animationLoop);
 | 
						|
  }
 | 
						|
  }
 | 
						|
 | 
						|
  let tt = false;
 | 
						|
  const stimeout = 500;
 | 
						|
  const changePage = (e, pbwork = true) => {
 | 
						|
    pbwork && document.querySelector("nav.navbar").classList.add("pbwork");
 | 
						|
    !tt && (tt = setTimeout(() => e.click(), stimeout));
 | 
						|
  };
 | 
						|
 | 
						|
  // <keybindings>
 | 
						|
  const clickOnElementBinding = selector => () => (elem = document.querySelector(selector)) ? elem.click() : null;
 | 
						|
  const keybindings = {
 | 
						|
    "ArrowLeft": clickOnElementBinding("#next"),
 | 
						|
    "a": clickOnElementBinding("#next"),
 | 
						|
    "ArrowRight": clickOnElementBinding("#prev"),
 | 
						|
    "d": clickOnElementBinding("#prev"),
 | 
						|
    "r": clickOnElementBinding("#random"),
 | 
						|
    " ": clickOnElementBinding("#f0ck-image")
 | 
						|
  };
 | 
						|
  document.addEventListener("keydown", e => {
 | 
						|
    if(e.key in keybindings && e.target.tagName !== "INPUT" &&  e.target.tagName !== "TEXTAREA") {
 | 
						|
      if(e.shiftKey || e.ctrlKey || e.metaKey || e.altKey)
 | 
						|
        return;
 | 
						|
      e.preventDefault();
 | 
						|
      keybindings[e.key]();
 | 
						|
    }
 | 
						|
  });
 | 
						|
  // </keybindings>
 | 
						|
 | 
						|
  // <image-responsive>
 | 
						|
  const imgSize = e => new Promise((res, _) => {
 | 
						|
    const i = new Image();
 | 
						|
    i.addEventListener('load', function() {
 | 
						|
      res({ width: this.width, height: this.height });
 | 
						|
    });
 | 
						|
    i.src = e.src;
 | 
						|
  });
 | 
						|
 | 
						|
  // <wheeler>
 | 
						|
  const wheelEventListener = function(event) {
 | 
						|
    if (event.target.closest('.media-object, .steuerung')) {
 | 
						|
      if (event.deltaY < 0) {
 | 
						|
        document.getElementById('next').click();
 | 
						|
      } else if (event.deltaY > 0) {
 | 
						|
        document.getElementById('prev').click();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  window.addEventListener('wheel', wheelEventListener);
 | 
						|
  // </wheeler>
 | 
						|
 | 
						|
 | 
						|
  if(f0ckimage = document.querySelector("img#f0ck-image")) {
 | 
						|
    const f0ckimagescroll = document.querySelector("#image-scroll");
 | 
						|
 | 
						|
    let isImageExpanded = false;
 | 
						|
    console.log("entry point - image unclicked")
 | 
						|
 | 
						|
    f0ckimage.addEventListener("click", async e => {
 | 
						|
      e.preventDefault();
 | 
						|
      const img = await imgSize(f0ckimage);
 | 
						|
      console.log("img clicked");
 | 
						|
      if (isImageExpanded) {
 | 
						|
        isImageExpanded = false;
 | 
						|
        f0ckimagescroll.removeAttribute("style");
 | 
						|
        f0ckimage.removeAttribute("style");
 | 
						|
        console.log("image is not expanded")
 | 
						|
        window.addEventListener('wheel', wheelEventListener);
 | 
						|
      } else {
 | 
						|
        if (img.width > img.height) return;
 | 
						|
        isImageExpanded = true;
 | 
						|
        window.removeEventListener('wheel', wheelEventListener);
 | 
						|
        f0ckimagescroll.setAttribute("style", "overflow-y: scroll");
 | 
						|
        f0ckimage.setAttribute("style", "max-height: none; height: auto; width: 100%; position: absolute; left: 0; border: var(--img-border-width) solid var(--img-border-color); border-top: none; border-bottom: none;");
 | 
						|
      }
 | 
						|
    });
 | 
						|
  }
 | 
						|
  // </image-responsive>
 | 
						|
 | 
						|
  // <scroller>
 | 
						|
  let tts = 0;
 | 
						|
  const scroll_treshold = 1;
 | 
						|
  if([...document.querySelectorAll("div.posts")].length === 1) {
 | 
						|
    document.addEventListener("wheel", e => {
 | 
						|
      if(Math.ceil(window.innerHeight + window.scrollY) >= document.querySelector('#main').offsetHeight && e.deltaY > 0) { // down
 | 
						|
        if(elem = document.querySelector(".pagination > .next:not(.disabled)")) {
 | 
						|
          if(tts < scroll_treshold) {
 | 
						|
            document.querySelector("div#footbar").style.boxShadow = "inset 0px 4px 0px var(--footbar-color)";
 | 
						|
            document.querySelector("div#footbar").style.color = "var(--footbar-color)";
 | 
						|
            tts++;
 | 
						|
          }
 | 
						|
          else
 | 
						|
            changePage(elem);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else if(window.scrollY <= 0 && e.deltaY < 0) { // up
 | 
						|
        if(elem = document.querySelector(".pagination > .prev:not(.disabled)")) {
 | 
						|
          if(tts < scroll_treshold) {
 | 
						|
            document.querySelector("nav.navbar").style.boxShadow = "0px 2px 0px var(--loading-indicator-color)";
 | 
						|
            document.querySelector("nav.navbar").style.transition = ".2s ease-in-out";
 | 
						|
            tts++;
 | 
						|
          }
 | 
						|
          else
 | 
						|
            changePage(elem);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        tts = 0;
 | 
						|
        document.querySelector("div#footbar").style.boxShadow = "unset";
 | 
						|
        document.querySelector("div#footbar").style.color = "transparent";
 | 
						|
        document.querySelector("nav.navbar").style.boxShadow = "unset";
 | 
						|
      }
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  const rmatch = /\/p\/(\d+?)/;
 | 
						|
  if(document.referrer.match(rmatch) && document.location.href.match(rmatch))
 | 
						|
    if(document.location.href.match(rmatch) < document.referrer.match(rmatch))
 | 
						|
      document.body.scrollTop = document.body.scrollHeight;
 | 
						|
  // </scroller>
 | 
						|
 
 | 
						|
  // <swipe>
 | 
						|
  const swipeRT = {
 | 
						|
    xDown: null,
 | 
						|
    yDown: null,
 | 
						|
    xDiff: null,
 | 
						|
    yDiff: null,
 | 
						|
    timeDown: null,
 | 
						|
    startEl: null
 | 
						|
  };
 | 
						|
  const swipeOpt = {
 | 
						|
    treshold: 20, // 20px
 | 
						|
    timeout: 500  // 500ms
 | 
						|
  };
 | 
						|
 | 
						|
  document.addEventListener('touchstart', e => {
 | 
						|
    swipeRT.startEl = e.target;
 | 
						|
    swipeRT.timeDown = Date.now();
 | 
						|
    swipeRT.xDown = e.touches[0].clientX;
 | 
						|
    swipeRT.yDown = e.touches[0].clientY;
 | 
						|
    swipeRT.xDiff = 0;
 | 
						|
    swipeRT.yDiff = 0;
 | 
						|
  }, false);
 | 
						|
 | 
						|
  document.addEventListener('touchmove', e => {
 | 
						|
    if(!swipeRT.xDown || !swipeRT.yDown)
 | 
						|
      return;
 | 
						|
    swipeRT.xDiff = swipeRT.xDown - e.touches[0].clientX;
 | 
						|
    swipeRT.yDiff = swipeRT.yDown - e.touches[0].clientY;
 | 
						|
  }, false);
 | 
						|
 | 
						|
  document.addEventListener('touchend', e => {
 | 
						|
    if(swipeRT.startEl !== e.target)
 | 
						|
      return;
 | 
						|
 | 
						|
    const timeDiff = Date.now() - swipeRT.timeDown;
 | 
						|
    let elem;
 | 
						|
 | 
						|
    if(Math.abs(swipeRT.xDiff) > Math.abs(swipeRT.yDiff)) {
 | 
						|
      if(Math.abs(swipeRT.xDiff) > swipeOpt.treshold && timeDiff < swipeOpt.timeout) {
 | 
						|
        if(swipeRT.xDiff > 0) // left
 | 
						|
          elem = document.querySelector(".pagination > .next:not(.disabled)");
 | 
						|
        else // right
 | 
						|
          elem = document.querySelector(".pagination > .prev:not(.disabled)");
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      if(Math.abs(swipeRT.yDiff) > swipeOpt.treshold && timeDiff < swipeOpt.timeout) {
 | 
						|
        if(navbar = document.querySelector("nav.navbar") && document.querySelector("div.posts")) {
 | 
						|
          if(swipeRT.yDiff > 0 && (window.innerHeight + window.scrollY) >= document.body.offsetHeight) // up
 | 
						|
            elem = document.querySelector(".pagination > .next:not(.disabled)");
 | 
						|
          else if(swipeRT.yDiff <= 0 && window.scrollY <= 0 && document.querySelector("div.posts")) // down
 | 
						|
            elem = document.querySelector(".pagination > .prev:not(.disabled)");
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    swipeRT.xDown = null;
 | 
						|
    swipeRT.yDown = null;
 | 
						|
    swipeRT.timeDown = null;
 | 
						|
 | 
						|
    if(elem)
 | 
						|
      changePage(elem);
 | 
						|
  }, false);
 | 
						|
  // </swipe>
 | 
						|
 | 
						|
  // <visualizer>
 | 
						|
  if(audioElement = document.querySelector("audio")) {
 | 
						|
    const canvas = document.createElement("canvas");
 | 
						|
    const ctx = canvas.getContext("2d");
 | 
						|
    canvas.width = 1920;
 | 
						|
    canvas.height = 1080;
 | 
						|
 | 
						|
    setTimeout(() => {
 | 
						|
      document.querySelector(".v0ck").insertAdjacentElement("afterbegin", canvas);
 | 
						|
    }, 400);
 | 
						|
 | 
						|
    const audioCtx = new AudioContext();
 | 
						|
    const analyser = audioCtx.createAnalyser();
 | 
						|
    analyser.fftSize = 2048;
 | 
						|
 | 
						|
    const source = audioCtx.createMediaElementSource(audioElement);
 | 
						|
    source.connect(analyser);
 | 
						|
    source.connect(audioCtx.destination);
 | 
						|
 | 
						|
    let data = new Uint8Array(analyser.frequencyBinCount);
 | 
						|
    requestAnimationFrame(loopingFunction);
 | 
						|
 | 
						|
    function loopingFunction() {
 | 
						|
      requestAnimationFrame(loopingFunction);
 | 
						|
      analyser.getByteFrequencyData(data);
 | 
						|
      draw(data);
 | 
						|
    }
 | 
						|
    function draw(data) {
 | 
						|
      data = [ ...data ];
 | 
						|
      ctx.clearRect(0, 0, canvas.width, canvas.height);
 | 
						|
      ctx.fillStyle = getComputedStyle(document.body).getPropertyValue("--accent");
 | 
						|
      data.forEach((value, i) => {
 | 
						|
        const percent = value / 256;
 | 
						|
        const height = (canvas.height * percent / 2) - 40;
 | 
						|
        const offset = canvas.height - height - 1;
 | 
						|
        const barWidth = canvas.width / analyser.frequencyBinCount;
 | 
						|
        ctx.fillRect(i * barWidth, offset, barWidth, height);
 | 
						|
      });
 | 
						|
    }
 | 
						|
    audioElement.onplay = () => {
 | 
						|
      audioCtx.resume();
 | 
						|
    };
 | 
						|
  }
 | 
						|
  // </visualizer>
 | 
						|
 | 
						|
  // <mediakeys>
 | 
						|
  if(elem = document.querySelector("#my-video") && "mediaSession" in navigator) {
 | 
						|
    const playpauseEvent = () => {
 | 
						|
      video[video.paused ? 'play' : 'pause']();
 | 
						|
      document.querySelector('.v0ck_overlay').classList[video.paused ? 'remove' : 'add']('v0ck_hidden');
 | 
						|
    };
 | 
						|
    navigator.mediaSession.setActionHandler('play', playpauseEvent);
 | 
						|
    navigator.mediaSession.setActionHandler('pause', playpauseEvent);
 | 
						|
    navigator.mediaSession.setActionHandler('stop', playpauseEvent);
 | 
						|
    navigator.mediaSession.setActionHandler('previoustrack', () => {
 | 
						|
      if(link = document.querySelector(".pagination > .prev:not(.disabled)"))
 | 
						|
        changePage(link);
 | 
						|
    });
 | 
						|
    navigator.mediaSession.setActionHandler('nexttrack', () => {
 | 
						|
      if(link = document.querySelector(".pagination > .next:not(.disabled)"))
 | 
						|
        changePage(link);
 | 
						|
    });
 | 
						|
  }
 | 
						|
  // </mediakeys>
 | 
						|
 | 
						|
  // <scroller>
 | 
						|
 | 
						|
  // </scroller>
 | 
						|
})();
 | 
						|
 | 
						|
// disable default scroll event when mouse is on content div
 | 
						|
// this is useful for items that have a lot of tags for example: 12536
 | 
						|
const targetSelector = '.content';
 | 
						|
let isMouseOver = true;
 | 
						|
 | 
						|
function isPageScrollable() {
 | 
						|
  return document.documentElement.scrollHeight > document.documentElement.clientHeight;
 | 
						|
}
 | 
						|
 | 
						|
function onWheel(e) {
 | 
						|
  if (isMouseOver && isPageScrollable()) {
 | 
						|
    e.preventDefault();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function init() {
 | 
						|
  const el = document.querySelector(targetSelector);
 | 
						|
    if (!el) return;
 | 
						|
      el.addEventListener('mouseenter', () => isMouseOver = true);
 | 
						|
      el.addEventListener('mouseleave', () => isMouseOver = false);
 | 
						|
      window.addEventListener('wheel', onWheel, { passive: false });
 | 
						|
}
 | 
						|
 | 
						|
window.addEventListener('load', init); |