NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name img2tab // @version 0.60 // @license MIT // @description Lightbox gallery for 4chan and image lists // @namespace https://openuserjs.org/scripts/img2tab/img2tab // @homepageURL https://openuserjs.org/scripts/img2tab/img2tab // @downloadURL https://openuserjs.org/install/img2tab/img2tab.user.js // @icon https://i.imgur.com/BSBMFSp.png // @compatible firefox // @match *://boards.4chan.org/*/thread/* // @match *://boards.4channel.org/*/thread/* // @match *://boards.420chan.org/*/res/* // @match *://8ch.net/*/res/* // @match file:///*/* // @grant none // ==/UserScript== var multiLineCSS = ` #lightboxGallery { display: block; position: absolute; left: 0; top: 0; z-index: 999; width: 100%; text-align: center; background-color: black; overflow: auto; } #lightboxGallery * { max-width: 100%; -moz-user-select: none; } .pcontainer { display: flex; flex-direction: column; justify-content: space-between; align-items: center; } .pcontainer:nth-child(odd) { background-color: #181818; } .pcontainer:nth-child(even) { background-color: #202020; } .pcontainer p { display: flex; align-items: center; justify-content: center; color: #666; margin: 0; padding: 1em 0; width: 100%; min-height: 2em; flex-direction: row; flex-flow: row wrap; flex-grow: 1; } .imageP img { max-height: 100vh; } #lightboxBackground { display: flex; position: fixed; left: 0; top: 0; width: 100%; height: 100%; background-color: black; color: white; text-align: center; align-items: flex-end; justify-content: center; } #pgupButton, #stretchButton, #removeButton { color: #fff; font-family: arial; position: fixed; opacity: 0.5; font-size: 2.5em; width: 1.2em; height: 1.2em; vertical-align: middle; text-align: center; border-radius: 0.6em; line-height: 1.2em; overflow: visible; top: 1em; -moz-user-select: none; cursor: pointer; background-color: #000; } #pgupButton:hover, #stretchButton:hover, #removeButton:hover { opacity: 0.9; } #removeButton { right: 1em; } #stretchButton { right: 2.5em; } #pgupButton { right: 4em; display: none; } html { width: 100%; overflow-x: hidden; } `; arrowPosition = 0 function addGlobalStyle(css) { var head = document.getElementsByTagName('head')[0]; if (!head) { head = document.createElement('head'); document.getElementsByTagName('html')[0].appendChild(head); } var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; head.appendChild(style); var stretch = document.createElement('style'); stretch.type = 'text/css'; stretch.id = 'stretchCSS'; head.appendChild(stretch); } function embedGalleryButton() { var galleryButton = document.createElement('a'); galleryButton.href = '#'; galleryButton.id = 'galleryButton'; galleryButton.style = 'margin-left: 0.5em;'; galleryButton.innerHTML = '[img2tab gallery]'; if (document.getElementsByClassName('navLinks desktop').length > 0) { document.getElementsByClassName('navLinks desktop')[0].appendChild(galleryButton); } else if (document.getElementById('expand-all-images')) { document.getElementById('expand-all-images').appendChild(galleryButton); } else { galleryButton.style = 'position: fixed; top: 4em; right: 12em;'; document.getElementsByTagName('body')[0].appendChild(galleryButton); } document.getElementById('galleryButton').addEventListener( 'click', embedGallery, false); } function inArray(elem, array) { if (array.indexOf) { return array.indexOf(elem); } for (var i = 0, length = array.length; i < length; i++) { if (array[i] === elem) { return i; } } return -1; } function collectLinks() { var links = content.document.getElementsByTagName('a'); var imageUrls = []; var count = 0; for (var i = 0; i < links.length; i++) { var url = links[i].href; if (url.match(/.+\.(jpg|gif|png|webm|mp4)$/i) && !url.match(/%3A%2F%2F/) && !url.match(/.+\.(jpg|gif|png|webm|mp4)\//i) && !url.match(/file_dl/i) && inArray(url, imageUrls) == -1) { imageUrls[count] = url; count++; } } return imageUrls; } function populateGallery(imageUrls) { var gallery = document.createElement('div'); gallery.id = 'lightboxGallery'; var removeButton = '<span id="removeButton">ðŸž</span>'; var stretchButton = '<span id="stretchButton">🞑</span>'; var pgupButton = '<span id="pgupButton">â–´</span>'; gallery.innerHTML = stretchButton + removeButton + pgupButton + imageUrls.reduce(function (s, url, i) { var line = ''; if (url.match(/\.(webm|mp4)/im)) { line = '<video src="' + url + '" controls></video>'; } else { line = '<img src="' + url + '" />'; } var anchori = 'anchor' + i.toString(); line = s + '<div class="pcontainer" id="' + anchori + '">' + '<p class="imageP countP ' + anchori + '">' + line + '</p></div>'; return line; }, ''); return gallery; } function embedBackground() { var lightboxBackground = document.createElement('div'); lightboxBackground.id = 'lightboxBackground'; lightboxBackground.innerHTML = '<span>END</span>'; document.getElementsByTagName('body')[0].appendChild(lightboxBackground); } function removeGallery() { document.getElementById('stretchCSS').innerHTML = ''; document.getElementById('lightboxGallery').outerHTML = ''; document.getElementById('lightboxBackground').outerHTML = ''; scroll(0, 0); } function stretchGallery() { var i; var stretch = document.getElementById('stretchCSS'); var anchors = document.getElementsByClassName('imageP'); if (stretch.innerHTML === '') { var multiLineCSS = ` html {overflow: -moz-scrollbars-none;} .pcontainer { min-height: 100vh; } .pcontainer p { padding: 0 !important; cursor: pointer; } #pgupButton { display: inherit !important; } `; stretch.innerHTML = multiLineCSS; for (i = 0; i < anchors.length - 1; i++) { anchors[i].addEventListener( 'click', scrolltoP, false); } } else { stretch.innerHTML = ''; for (i = 0; i < anchors.length - 1; i++) { anchors[i].removeEventListener( 'click', scrolltoP, false); } } scrollarrow(arrowPosition) } function scrolltoP() { var i = this.className; i = i.match(/[0-9][0-9]*/)[0]; i = parseInt(i, 10); i += 1; arrowPosition = i; i = 'anchor' + i.toString(); document.getElementById(i).scrollIntoView(true); } function scrollarrow(i) { i = 'anchor' + i.toString(); document.getElementById(i).scrollIntoView(true); } function scrollBack() { arrowPosition--; if (arrowPosition < 0) { arrowPosition = document.getElementsByClassName('imageP').length - 1 } scrollarrow(arrowPosition); } function scrollForward() { arrowPosition++; if (arrowPosition > document.getElementsByClassName('imageP').length - 1) { arrowPosition = 0 } scrollarrow(arrowPosition); } function listentoButtons() { document.getElementById('removeButton').addEventListener( 'click', removeGallery, false); document.getElementById('stretchButton').addEventListener( 'click', stretchGallery, false); document.getElementById('pgupButton').addEventListener( 'click', scrollBack, false); } function embedGallery() { imageUrls = collectLinks(); gallery = populateGallery(imageUrls); document.getElementById('galleryButton').parentElement.appendChild(gallery); embedBackground(); scroll(0, 0); listentoButtons(); } addGlobalStyle(multiLineCSS); embedGalleryButton(); document.onkeydown = function (e) { switch (e.keyCode) { case 37: scrollBack(); break; case 39: scrollForward(); break; } };