Last active
February 6, 2018 21:15
-
-
Save vsemozhetbyt/f26932dfc20b43dee8540e8a669989e9 to your computer and use it in GitHub Desktop.
This file contains 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
/* ************************************************************************** */ | |
// ==UserScript== | |
// @name News Bookmark Instagram | |
// @namespace vsemozhetbyt | |
// @description News Reading from Bookmark in Instagram | |
// @version 1 | |
// @include https://www.instagram.com/* | |
// @noframes | |
// @grant none | |
// @nocompat Chrome | |
// ==/UserScript== | |
/* ************************************************************************** */ | |
'use strict'; | |
(() => { | |
const d = document; | |
const b = d.body; | |
if (d.querySelector('[data-vmb-news-div]')) return; | |
const funcs = [ | |
{ | |
name: '\u221e', | |
func: bookmarkFind, | |
}, { | |
name: '\u25b2', | |
func: navToPost, | |
args: 'getPrevPost', | |
}, { | |
name: '\u25bc', | |
func: navToPost, | |
args: 'getNextPost', | |
}, { | |
name: '\u00a0\u222b\u00a0', | |
func: bookmarkSave, | |
}, | |
]; | |
const opts = { | |
'www.instagram.com': { | |
additionalCSS: '[data-vmb-news-div] { display: block !important; }', | |
idLinkSelector: 'div._mck9w._gvoze._tn0ps a[href]', | |
getPost: nd => nd.closest('div._mck9w._gvoze._tn0ps'), | |
getIdLink: nd => nd.querySelector('a[href]'), | |
getBookmark: url => d.querySelector(`a[href='${url}']`), | |
getPostgroupAncestor: nd => nd.closest('div._6d3hm._mnav9'), | |
getPrevPost: nd => xp(`./preceding::div[${xpClass('_mck9w _gvoze _tn0ps')}][1]`, nd), | |
getNextPost: nd => xp(`./following::div[${xpClass('_mck9w _gvoze _tn0ps')}]`, nd), | |
scrollTop: -55, | |
storage: IDB, | |
siteFuncs: ['\u221e', '\u25b2', '\u25bc', '\u00a0\u222b\u00a0'], | |
autoload: [bookmarkFind], | |
}, | |
}; | |
const opt = opts[location.hostname]; | |
if (!opt) { | |
alert('Wrong site.'); | |
return; | |
} | |
const newsSt = b.appendChild(d.createElement('style')); | |
newsSt.setAttribute('data-vmb-news-style', ''); | |
newsSt.textContent = ` | |
[data-vmb-news-div] { position: fixed; top: 0px; left: 50%; z-index: 10000; padding: 2px !important; background-color: gainsboro !important; outline: 1px solid black !important; } | |
[data-vmb-news-div] * { margin: 0px 2px !important; } | |
${opt.additionalCSS || ''} | |
`; | |
if (opt.getBookmark || opt.getPrevPost) { | |
const bmkNavSt = b.appendChild(d.createElement('style')); | |
bmkNavSt.setAttribute('data-vmb-bookmark-nav-style', ''); | |
bmkNavSt.textContent = ` | |
body { counter-reset: vmb-bookmark-nav-counter; } | |
${opt.idLinkSelector}:before { content: counter(vmb-bookmark-nav-counter, decimal-leading-zero)'. '; counter-increment: vmb-bookmark-nav-counter; } | |
[data-vmb-focus], [data-vmb-focus] ${opt.idLinkSelector} { outline: 1px solid lime !important; } | |
[data-vmb-bookmark], [data-vmb-bookmark] *, [data-vmb-bookmark] ~ *, [data-vmb-bookmark] ~ * * { background-color: gainsboro !important; } | |
${opt.getPostgroupAncestor ? '[data-vmb-bookmark-postgroup-ancestor] ~ *, [data-vmb-bookmark-postgroup-ancestor] ~ * * { background-color: gainsboro !important; }' : ''} | |
`; | |
b.addEventListener('mouseup', setFocus); | |
} | |
const newsDiv = d.createElement('div'); | |
newsDiv.setAttribute('data-vmb-news-div', ''); | |
funcs.forEach( | |
(func) => { | |
if (opt.siteFuncs.includes(func.name)) { | |
const btn = newsDiv.appendChild(d.createElement('button')); | |
btn.type = 'button'; | |
btn.textContent = func.name; | |
btn.addEventListener('click', () => { func.func(func.args); }); | |
} | |
}, | |
); | |
b.appendChild(newsDiv); | |
if (opt.autoload) opt.autoload.forEach((func) => { func(); }); | |
function setFocus(evt) { | |
const newFocus = opt.getPost(evt.target); | |
if (newFocus) { | |
const oldFocus = d.querySelector('[data-vmb-focus]'); | |
if (oldFocus) oldFocus.removeAttribute('data-vmb-focus'); | |
newFocus.setAttribute('data-vmb-focus', ''); | |
} | |
} | |
function bookmarkFind() { | |
opt.storage(`vmb_bookmark_${location.href}`, null, (url) => { | |
if (!url) { | |
alert('Bookmark not found. Save a new one.'); | |
return; | |
} | |
const idLink = opt.getBookmark(url); | |
let focus; | |
if (idLink) focus = opt.getPost(idLink); | |
if (focus) { | |
const oldBookmark = d.querySelector('[data-vmb-bookmark]'); | |
if (oldBookmark) oldBookmark.removeAttribute('data-vmb-bookmark'); | |
focus.setAttribute('data-vmb-bookmark', ''); | |
if (opt.getPostgroupAncestor) { | |
const oldBookmarkAncestor = d.querySelector('[data-vmb-bookmark-postgroup-ancestor]'); | |
if (oldBookmarkAncestor) { | |
oldBookmarkAncestor.removeAttribute('data-vmb-bookmark-postgroup-ancestor'); | |
} | |
opt.getPostgroupAncestor(focus).setAttribute('data-vmb-bookmark-postgroup-ancestor', ''); | |
} | |
setFocus({ target: idLink }); | |
focus.scrollIntoView(true); | |
scrollBy(0, opt.scrollTop); | |
} else { | |
scrollTo(0, b.scrollHeight); | |
} | |
}); | |
} | |
function bookmarkSave() { | |
const focus = d.querySelector('[data-vmb-focus]'); | |
if (focus) { | |
const idLink = opt.getIdLink(focus); | |
if (idLink) { | |
const oldBookmark = d.querySelector('[data-vmb-bookmark]'); | |
if (oldBookmark) oldBookmark.removeAttribute('data-vmb-bookmark'); | |
focus.setAttribute('data-vmb-bookmark', ''); | |
if (opt.getPostgroupAncestor) { | |
const oldBookmarkAncestor = d.querySelector('[data-vmb-bookmark-postgroup-ancestor]'); | |
if (oldBookmarkAncestor) oldBookmarkAncestor.removeAttribute('data-vmb-bookmark-postgroup-ancestor'); | |
opt.getPostgroupAncestor(focus).setAttribute('data-vmb-bookmark-postgroup-ancestor', ''); | |
} | |
opt.storage(`vmb_bookmark_${location.href}`, idLink.getAttribute('href')); | |
} else { | |
alert('Sorry. Strange post. Select another one.'); | |
} | |
} else { | |
alert('Click on the post.'); | |
} | |
} | |
function navToPost(dirFunk) { | |
const focus = d.querySelector('[data-vmb-focus]'); | |
if (focus) { | |
const scrollPad = 50; | |
const destPost = opt[dirFunk](focus); | |
if (destPost) { | |
setFocus({ target: destPost.querySelector('a[href]') }); | |
if (opt[dirFunk](destPost)) { | |
destPost.scrollIntoView(true); | |
scrollBy(0, opt.scrollTop); | |
} else if (dirFunk === 'getPrevPost') { | |
; | |
} else { | |
scrollBy(0, scrollPad); | |
} | |
} else if (dirFunk === 'getPrevPost') { | |
; | |
} else { | |
scrollBy(0, scrollPad); | |
} | |
} else { | |
const idLink = b.querySelector(opt.idLinkSelector); | |
setFocus({ target: idLink }); | |
opt.getPost(idLink).scrollIntoView(true); | |
scrollBy(0, opt.scrollTop); | |
} | |
} | |
function IDB(key, value, func) { | |
const openRequest = indexedDB.open('vmbIDBNews', 1); | |
openRequest.onerror = (evtErr) => { console.error(evtErr.target.error); }; | |
openRequest.onupgradeneeded = (evt) => { evt.target.result.createObjectStore('news'); }; | |
openRequest.onsuccess = (evt) => { | |
const db = evt.target.result; | |
db.onerror = (evtErr) => { console.error(evtErr.target.error); db.close(); }; | |
if (value) { | |
db.transaction('news', 'readwrite') | |
.objectStore('news') | |
.put(value, key) | |
.onsuccess = () => { db.close(); }; | |
} else { | |
db.transaction('news', 'readonly') | |
.objectStore('news') | |
.get(key) | |
.onsuccess = (evtGet) => { func(evtGet.target.result); db.close(); }; | |
} | |
}; | |
} | |
function xp(expression, contextNode = b) { | |
return d.evaluate( | |
expression, contextNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null, | |
).singleNodeValue; | |
} | |
function xpClass(clsName) { | |
return `contains(concat(" ", normalize-space(@class), " "), " ${clsName} ")`; | |
} | |
})(); |
Author
vsemozhetbyt
commented
Jan 28, 2018
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment