Last active
February 6, 2022 03:34
-
-
Save gullinbursti/cefefea9db8a44389348070d87c92ed1 to your computer and use it in GitHub Desktop.
DOM Manipulation + Injection for Firefox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// overwrite history events for url change | |
(()=> { | |
var pushState = history.pushState; | |
var replaceState = history.replaceState; | |
history.pushState = function() { | |
pushState.apply(history, arguments); | |
window.dispatchEvent(new Event('pushstate')); | |
window.dispatchEvent(new Event('locationchange')); | |
}; | |
history.replaceState = function() { | |
replaceState.apply(history, arguments); | |
window.dispatchEvent(new Event('replacestate')); | |
window.dispatchEvent(new Event('locationchange')); | |
}; | |
window.addEventListener('popstate', function() { | |
window.dispatchEvent(new Event('locationchange')) | |
}); | |
})(); | |
// remove all added extractor elements | |
(()=> { | |
const css = Array.from(document.head.children).filter((el)=> (el.getAttribute('data-id') === 'vsco-extractor')).pop(); | |
if (css) { | |
css.remove(); | |
} | |
Array.from(document.querySelectorAll('.vsco-extractor')).forEach((el)=> { el.remove(); }); | |
})(); | |
// add img btn + info to gallery thumbs | |
(()=> { | |
const MONTH_NAMES = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']; | |
const imgDimSort = (dims)=> ([... new Set(dims.sort((dim1, dim2)=> ((dim1.height - dim2.height))).sort((dim1, dim2)=> ((dim1.width - dim2.width))).map((el)=>(el.toString()))) ].map((el)=>(el.split(',')))); | |
const toggleLarges = ()=> { | |
btnToggle.selected = !brnToggle.selected; | |
btnToggle.innerHTML = `` | |
Array.from(document.querySelectorAll('.MediaThumbnail')).filter((thumb)=> ((!thumb.classList.contains('dim-lg')))).forEach((thumb)=> { | |
thumb.classList.toggle('is-hidden'); | |
//thumb.querySelector('.MediaImage > div').classList.toggle('shrink-down'); | |
}); | |
}; | |
let scrollLoader = null; | |
let dimLarges = []; | |
let gridThumbs = { | |
load : { | |
prev : [], | |
curr : [], | |
isLoading : false | |
}, | |
disp : { | |
img : { | |
small : [], | |
orthodox : [], | |
large : [], | |
sizes : [] | |
}, | |
vid : { | |
enabled : [], | |
disabled : [] | |
} | |
} | |
}; | |
const galleryCheck = ()=> { | |
const hasPanel = (document.querySelector('.vsco-extractor-dash-panel') != null); | |
if (location.pathname.includes('gallery')) { | |
let preThumbs = Array.from(document.querySelectorAll('.grid .MediaThumbnail')); | |
const loadBtn = document.querySelector('main > div > div > section > div > button'); | |
gridThumbs = { ...gridThumbs, | |
load : { | |
prev : [ ...preThumbs ], | |
curr : [ ...preThumbs ] | |
} | |
}; | |
if (!hasPanel) { | |
document.querySelector('.page-wrap').appendChild(dashPanel); | |
} | |
if (loadBtn) { | |
gridThumbs = { ...gridThumbs, | |
load : { ...gridThumbs.load, | |
isLoading : true | |
} | |
}; | |
loadBtn.scrollIntoView(); | |
loadBtn.click(); | |
scrollLoader = setInterval(()=> { | |
const spinner = document.querySelector('main > div > div > section > div > svg'); | |
preThumbs = Array.from(document.querySelectorAll('.grid .MediaThumbnail')); | |
gridThumbs = { ...gridThumbs, | |
load : { ...gridThumbs.load, | |
prev : gridThumbs.load.curr, | |
curr : [ ...preThumbs ] | |
} | |
}; | |
const { load } = gridThumbs; | |
const { prev, curr } = load; | |
console.log('gridThumbs.load', { ...load }, { loadBtn, spinner }); | |
gridUpdate(); | |
// if (prev === curr && !document.querySelector('main div > svg')) { | |
if (prev.length === curr.length && (!spinner || !loadBtn)) { | |
clearInterval(scrollLoader); | |
scrollLoader = null; | |
gridThumbs = { ...gridThumbs, | |
load : { ...gridThumbs.load, | |
isLoading : true | |
} | |
}; | |
} | |
window.scrollByPages(((prev.length === curr.length) << 0) * -1); | |
window.scrollBy(0, window.scrollMaxY); | |
setTimeout(()=> { window.scrollBy(0, window.scrollMaxY); }, (1 + ((prev.length === curr.length) << 0) * 69)); | |
}, 666); | |
} | |
} else { | |
clearInterval(scrollLoader); | |
scrollLoader = null; | |
if (hasPanel) { | |
document.querySelector('.page-wrap').removeChild(dashPanel); | |
} | |
} | |
}; | |
const gridUpdate = ()=> { | |
const totThumbs = Array.from(document.querySelectorAll('.grid figure.MediaThumbnail')).length; | |
const totVids = Array.from(document.querySelectorAll('.grid video')).length; | |
const accVids = Array.from(document.querySelectorAll('.grid video')).filter((v)=> (v.currentSrc.length > 0)).length; | |
const totImgs = totThumbs - totVids; | |
//imgDate.innerHTML = `${Date().now().toLocaleString().split(',').shift()}`; | |
firstDate.innerHTML = `<<-- ${((totThumbs > 0) ? new Date(Array.from(document.querySelectorAll('.MasonryGridLayout-column')).map((col)=> (Object.values(col.lastChild).shift().return.pendingProps.media)).map((media)=> ((((media.captureDate || media.createdDate) || media.uploadDate) || Date.now()))).sort().reverse().pop()) : Date.now()).toLocaleString().split(',').shift()}`; | |
let imgDims = []; | |
gridStats.innerHTML = ` | |
<h6 class="vsco-extractor">Total : ${totThumbs}</h6> | |
<div>Images : ${totImgs}</div><div>Videos : ${accVids}${(totVids > accVids) ? ` (${totVids - accVids})` : ''}</div>`; | |
// iterate over grid items w/o injection yet | |
Array.from(document.querySelectorAll('.grid .MediaThumbnail')).filter((thumb)=> ((!thumb.classList.contains('vsco-extractor')))).forEach((thumb)=> { | |
thumb.classList.add('vsco-extractor'); | |
const { media, mediaIndex } = Object.values(thumb).shift().return.pendingProps; | |
const { captureDate, createdDate, uploadDate, responsiveUrl, width, height, isVideo, videoUrl } = media; | |
const url = `https://${(!isVideo) ? responsiveUrl : videoUrl}`; | |
const size = { width, height }; | |
const pubDate = (((captureDate || createdDate) || uploadDate) || Date.now()); | |
imgDims.push(size); | |
const imgWrapper = (!isVideo) ? thumb.querySelector('.MediaImage') : thumb.querySelector('div'); | |
const btnFullImg = document.createElement('button'); | |
btnFullImg.classList.add('vsco-extractor-btn'); | |
btnFullImg.classList.add('full-image-btn'); | |
if ((size.width << 0) >= 4032 || (size.height << 0) >= 4032) { | |
thumb.classList.add('dim-lg'); | |
btnFullImg.classList.add('dim-lg-btn'); | |
imgWrapper.classList.add('vsco-extractor-img-lg'); | |
dimLarges.push(thumb); | |
} | |
//console.log('[>> size ]', JSON.stringify(size, null, 2)); | |
btnFullImg.innerHTML = `${size.width} x ${size.height}`; | |
btnFullImg.disabled = (isVideo && thumb.querySelector('video').currentSrc.length === 0); | |
btnFullImg.onclick = (e)=> { e.target.blur(); window.open(url, '_blank'); }; | |
thumb.insertAdjacentElement('afterBegin', btnFullImg); | |
const timestamp = document.createElement('div'); | |
timestamp.classList.add('vsco-extractor'); | |
timestamp.classList.add('vsco-extractor-timestamp'); | |
timestamp.innerHTML = `(#${mediaIndex + 1}) ${(new Date(pubDate)).toLocaleString().split(',').shift()}`; | |
thumb.insertAdjacentElement('beforeEnd', timestamp); | |
}); | |
const { prev, curr, isLoading } = gridThumbs.load | |
const { img } = gridThumbs.disp; | |
gridThumbs = { ...gridThumbs, | |
disp : { ...gridThumbs.disp, | |
img : { ...img, large : dimLarges } | |
} | |
}; | |
btnToggle.innerHTML = `Toggle Larges (${dimLarges.length})`; | |
btnToggle.disabled = (dimLarges.length === 0 && !isLoading); | |
btnToggle.onclick = (!btnToggle.disabled) ? (e)=> { | |
e.preventDefault(); | |
e.target.blur(); | |
window.scrollTo(0, 425); | |
toggleLarges(); | |
} : null; | |
console.log('img dims ASC w,hd', imgDimSort(imgDims)); | |
}; | |
const css = document.createElement('style'); | |
css.setAttribute('type', 'text/css'); | |
css.setAttribute('media', 'screen'); | |
css.setAttribute('data-id', 'vsco-extractor'); | |
css.innerHTML = ` | |
button:hover { | |
cursor: pointer; | |
} | |
button[disabled] { | |
cursor: not-allowed; | |
} | |
h6.vsco-extractor { | |
margin-bottom: 3px; | |
border-bottom: 1px solid #000000; | |
line-height: normal; | |
font-weight: bold; | |
font-size: 1.1em; | |
} | |
.is-hidden { | |
display: none; | |
} | |
.shrink-down { | |
height: 0; | |
} | |
.vsco-extractor { | |
font-family: Consolas, Monaco, "Courier New", Courier, monospace; | |
font-size: 12px; | |
} | |
.vsco-extractor .vsco-extractor-btn { | |
border: 1px solid #ffffff; | |
} | |
.vsco-extractor .vsco-extractor-btn[disabled], .vsco-extractor .vsco-extractor-btn[disabled]:hover { | |
border: 1px solid #4a4a4a; | |
opacity: 0.25; | |
filter: brightness(85%); | |
cursor: not-allowed; | |
} | |
.vsco-extractor-dash-panel { | |
position: fixed; | |
top: 0; | |
right: 0; | |
width: auto; | |
padding: 3px; | |
border: 1px solid rgba(0, 0, 0, 1.0); | |
background-color: rgba(0, 0, 0, 0.5); | |
text-align: right; | |
font-size: 0.9em; | |
z-index: 1001; | |
} | |
.vsco-extractor-grid-stats { | |
color: rgba(0, 255, 255, 0.875); | |
font-size: 0.8em; | |
line-height: 1.333em; | |
text-shadow: 0px 0px 5px rgba(0, 0, 0, 1.0); | |
} | |
.vsco-extractor-first-date { | |
margin: 4px 3px; | |
font-size: 0.6em; | |
color: e0e0e0; | |
} | |
.vsco-extractor .toggle-dim-btn { | |
margin-top: 4px; | |
padding: 4px 4px 6px 4px; | |
border: none; | |
background-color: rgba(255, 255, 255, 0.75); | |
color: #ffffff; | |
font-size: 0.7em; | |
} | |
.vsco-extractor .grid-img-lg { | |
border: 2px solid rgba(192, 0, 192, 0.75); | |
transition: border-color 0.125s linear 0s; | |
} | |
.vsco-extractor .grid-img-lg:hover { | |
border: 2px solid rgba(255, 0, 255, 1); | |
transition: border-color 0.625s ease-in 0.125; | |
} | |
.vsco-extractor .full-image-btn { | |
position: absolute; | |
left: 0; | |
width: 100%; | |
padding: 3px 0 4px 0; | |
background-color: rgba(27, 33, 33, 1.0); | |
opacity: 0.5; | |
color: rgba(255, 255, 255, 0.875); | |
font-size: 1em; | |
font-weight: bold; | |
line-height: normal; | |
border: 1px solid rgba(255, 255, 255, 0.25); | |
text-shadow: 0px 0px 3px rgba(0, 0, 0, 1.0); | |
/* filter: brightness(100%); */ | |
/* transition: opacity 0.125s ease-in 0s, filter 0.125s, ease-in 0s; */ | |
transition: opacity 0.125s ease-in 0s; | |
/* transition: filter 0.125s, ease-in 0s; */ | |
z-index: 101; | |
} | |
.vsco-extractor .full-image-btn:hover { | |
opacity: 0.875; | |
filter: brightness(105%); | |
/* transition: opacity 0.333s ease-out 0s, filter 0.333s, ease-in 0s; */ | |
} | |
.vsco-extractor .dim-lg-btn { | |
background-color: rgba(255, 0, 255, 0.875); | |
border: 1px solid rgba(255, 0, 255, 0.5); | |
border-bottom: 1px dotted rgba(0, 0, 0, 1.0); | |
color: #ffff00; | |
opacity: 0.75; | |
} | |
.vsco-extractor .dim-lg-btn:hover { | |
opacity: 1.0; | |
filter: brightness(115%); | |
} | |
.vsco-extractor-timestamp { | |
position: absolute; | |
right: 0; | |
bottom: 22px; | |
padding: 2px; | |
color: #808080; | |
font-size: 0.8em; | |
line-height: normal; | |
} | |
.MediaThumbnail { | |
position: relative; | |
transition: height 0.5s linear 0s; | |
} | |
.MediaThumbnail .MediaImage > div { | |
height: auto; | |
transition: background-color 0.2s ease 0s; | |
} | |
.MediaThumbnail .MediaImage > div.shrink-down { | |
height: 0; | |
/*transition: background-color 0.2s ease 0s; */ | |
transition: height 1s linear 0s; | |
} | |
`; | |
document.head.appendChild(css); | |
const dashPanel = document.createElement('div'); | |
dashPanel.classList.add('vsco-extractor'); | |
dashPanel.classList.add('vsco-extractor-dash-panel'); | |
const gridStats = document.createElement('div'); | |
gridStats.classList.add('vsco-extractor-grid-stats'); | |
const firstDate = document.createElement('div'); | |
firstDate.classList.add('vsco-extractor-first-date'); | |
const btnToggle = document.createElement('button'); | |
btnToggle.classList.add('vsco-extractor-btn'); | |
btnToggle.classList.add('toggle-dim-btn'); | |
dashPanel.appendChild(gridStats); | |
dashPanel.appendChild(firstDate); | |
dashPanel.appendChild(btnToggle); | |
// dashPanel.insertAdjacentElement('beforeEnd', btnToggle); | |
//setTimeout(()=> { galleryCheck(); }, 1000); | |
//galleryCheck(); | |
window.onload = ()=> { | |
console.log('window.LOAD -->'); | |
setTimeout(galleryCheck, 333); | |
}; | |
// window.document.addEventListener('load', ()=> { | |
// console.log('window.LOAD -->';) | |
// galleryCheck(); | |
// }); | |
window.addEventListener('locationchange', ()=> { | |
console.log('window.locationChanged', location); | |
//galleryCheck(); | |
setTimeout(galleryCheck, 333); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment