just as a side note I am new to JS and this is my first script.
I am writing a small script that should allow me to open the biggest available image in a flickr page in an unfocused newtab using a keyboard shortcut.
I am currently facing two problems:
The script is slow at loading, meaning that if I change the image in the slideshow using the arrow keys, I will need to wait 1 or 2 seconds before pressing the keyboard shortcut to open the image in the newtab. If I don't wait, it will open one of the previous images from the slideshow in the newtab depending on how fast I was skipping through them. (It should always open the image I am currently viewing in a newtab)
I use log(mainurl) to print the current contents of "mainurl" which is the link to the biggest available size of the current opened image. but for some reason it is always giving me the url of one of the previous images depending on how fast I am skipping through the slideshow (even though the correct image is opened in the newtab).
Here is a URL to a flickr account if you want to check the script. (it must be run in the photostream [slideshow mode]) URL to flickr photostream
This is the code I wrote
// ==UserScript==
// @name Flickr Max NewTab
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Open Max sized flickr image in a new tab using key shorcut
// @author Newbie
// @include /flickr\.com/
// @grant GM_openInTab
// @require https://code.jquery.com/jquery-3.3.1.min.js
// ==/UserScript==
var page ='';
var sizes = [];
var links = [];
var length = 0;
var mainurl = '';
function geturl() { // function used to get the link of biggest image
var action = function (sourceCode) {
sizes = sourceCode.match(/modelExport: {.+?"sizes":{.+?}}/i); // extract the part of html that containes modelExport:
links = sizes[0].match(/"displayUrl":"[^"]+"/ig); // extract the urls dictionary from the dictionary modelExport:
length = links.length; //get the length of the dictionary "links"
// extract the last(biggest) url from the links dictionary and put them in an array "links"
mainurl = links[links.length-1].replace(/"displayUrl":"([^"]+)"/i, "$1").replace(/\\/g, "").replace(/(_[a-z])\.([a-z]{3,4})/i, '$1' + "." + '$2');
}
$.get(document.URL, action);
}
function log(x) {
console.log(x);
}
// function used to get to run the url grabber everytime you change the image in slideshow using arrowkeys
function navigation (e) {
if (e.keyCode == 37 || e.keyCode == 39) {
geturl();
log(mainurl);// log to check the current contents of mainurl
}
}
// function used to open image in a newtab when "alt + Q" are pressed
function newtab (e) {
if (e.altKey && e.keyCode == 81) {
GM_openInTab(mainurl);
}
}
geturl(); //run the function
document.addEventListener('keyup', navigation);
document.addEventListener('keydown', newtab);
Thanks a lot for any help !
It's best to intercept the existing fast request made by the site to its server API (you can inspect it in devtools network panel) instead of making an additional slow request.
For that we will use unsafeWindow
and hook XMLHttpRequest
prototype. Also run the script at document-start
so it attaches the interceptor before the page makes the request.
// ==UserScript==
// @name Flickr Max NewTab
// @match https://www.flickr.com/*
// @grant GM_openInTab
// @run-at document-start
// ==/UserScript==
const xhrOpen = unsafeWindow.XMLHttpRequest.prototype.open;
unsafeWindow.XMLHttpRequest.prototype.open = function (method, url) {
if (/method=[^&]*?(getPhotos|getInfo)/.test(url)) {
this.addEventListener('load', onXhrLoad, {once: true});
}
return xhrOpen.apply(this, arguments);
};
const imgUrls = {};
function onXhrLoad() {
const json = JSON.parse(this.response);
const photos = json.photos ? json.photos.photo : [json.photo];
for (const {id, url_o} of photos) {
imgUrls[id] = url_o;
}
}
document.addEventListener('keydown', e => {
if (e.altKey && e.code === 'KeyQ' && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
const id = location.pathname.split('/')[3];
const url = imgUrls[id];
if (url) GM_openInTab(url, true);
}
});