Creating and updating link to instagram image or video
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
I've been using the InstagramPhotoLink extension for Opera for some time but instagram broke it recently. I thought I could try to fix it... and I did.
The original extension is rather limited and it supports only a link to the first image and no videos so while fixing it I completely rewrote it in order to extend it.
It works by looking for an image
or video
element with a specific class
and extracts the src
attribute from it and puts it in a new a
-element inside the media-container.
Switching images/videos is supported by the MutationObserver
that updates the links when either a div
or an attribute changes.
I came across a problem where the MutatorObserver
reacts too quickly and before the src
attribute of the new image is set. I solved it by adding a small delay by adding a call to setTimeout
to wait until everything is updated.
function createMediaLink()
function addOrUpdateImageLink(mo)
let image = document.getElementsByClassName('FFVAD');
if (image.length == 0)
return false;
image = image[0];
if (mo)
// the nearest div to the image that stays there when switching images
var div = document.getElementsByClassName("rQDP3");
mo.observe(div[0],
childList: true
);
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
return true;
function addOrUpdateVideoLink(mo)
let video = document.getElementsByClassName('tWeCl');
if (video.length == 0)
return false;
video = video[0];
if (mo)
mo.observe(video,
attributes: true
);
setTimeout(() =>
addOrUpdateMediaLink(video.src);
, 50);
return true;
function addOrUpdateMediaLink(src)
console.log(`src: $src`);
let a = document.getElementsByClassName('_open_');
if (a.length == 0)
a = document.createElement("a");
a.className = "_open_";
a.innerHTML = 'Open in new tab';
a.target = "_blank";
// media container
document.getElementsByClassName("_97aPb")[0].appendChild(a);
else
a = a[0];
a.href = src;
createMediaLink();
I don't write javascript too often so this is the best I can do but I'm pretty sure this can still be improved. What do you think?
javascript ecmascript-6 instagram
add a comment |Â
up vote
3
down vote
favorite
I've been using the InstagramPhotoLink extension for Opera for some time but instagram broke it recently. I thought I could try to fix it... and I did.
The original extension is rather limited and it supports only a link to the first image and no videos so while fixing it I completely rewrote it in order to extend it.
It works by looking for an image
or video
element with a specific class
and extracts the src
attribute from it and puts it in a new a
-element inside the media-container.
Switching images/videos is supported by the MutationObserver
that updates the links when either a div
or an attribute changes.
I came across a problem where the MutatorObserver
reacts too quickly and before the src
attribute of the new image is set. I solved it by adding a small delay by adding a call to setTimeout
to wait until everything is updated.
function createMediaLink()
function addOrUpdateImageLink(mo)
let image = document.getElementsByClassName('FFVAD');
if (image.length == 0)
return false;
image = image[0];
if (mo)
// the nearest div to the image that stays there when switching images
var div = document.getElementsByClassName("rQDP3");
mo.observe(div[0],
childList: true
);
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
return true;
function addOrUpdateVideoLink(mo)
let video = document.getElementsByClassName('tWeCl');
if (video.length == 0)
return false;
video = video[0];
if (mo)
mo.observe(video,
attributes: true
);
setTimeout(() =>
addOrUpdateMediaLink(video.src);
, 50);
return true;
function addOrUpdateMediaLink(src)
console.log(`src: $src`);
let a = document.getElementsByClassName('_open_');
if (a.length == 0)
a = document.createElement("a");
a.className = "_open_";
a.innerHTML = 'Open in new tab';
a.target = "_blank";
// media container
document.getElementsByClassName("_97aPb")[0].appendChild(a);
else
a = a[0];
a.href = src;
createMediaLink();
I don't write javascript too often so this is the best I can do but I'm pretty sure this can still be improved. What do you think?
javascript ecmascript-6 instagram
Do you use this when viewing a list of images/videos and/or when viewing a single item (and navigating through a collection - e.g. using left/right clicks/arrow key presses)?
â Sam Onela
Jun 11 at 4:20
@SamOnela this works only in single item view, not lists.
â t3chb0t
Jun 11 at 4:23
Okay - I am trying to see the linevar div = document.getElementsByClassName("rQDP3");
working... if I go to the album view cats_of_instagram I don't see any results there, then if I click on an item, it opens the modal but I still don't see any results there... if I refresh the item is displayed but not in a modal. When do you see results for that?
â Sam Onela
Jun 11 at 16:01
@SamOnela try this class name_97aPb
- this seems to be a more common one that works on any page. I see that the one I used in my question applies only to certain pages :-|
â t3chb0t
Jun 11 at 16:12
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I've been using the InstagramPhotoLink extension for Opera for some time but instagram broke it recently. I thought I could try to fix it... and I did.
The original extension is rather limited and it supports only a link to the first image and no videos so while fixing it I completely rewrote it in order to extend it.
It works by looking for an image
or video
element with a specific class
and extracts the src
attribute from it and puts it in a new a
-element inside the media-container.
Switching images/videos is supported by the MutationObserver
that updates the links when either a div
or an attribute changes.
I came across a problem where the MutatorObserver
reacts too quickly and before the src
attribute of the new image is set. I solved it by adding a small delay by adding a call to setTimeout
to wait until everything is updated.
function createMediaLink()
function addOrUpdateImageLink(mo)
let image = document.getElementsByClassName('FFVAD');
if (image.length == 0)
return false;
image = image[0];
if (mo)
// the nearest div to the image that stays there when switching images
var div = document.getElementsByClassName("rQDP3");
mo.observe(div[0],
childList: true
);
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
return true;
function addOrUpdateVideoLink(mo)
let video = document.getElementsByClassName('tWeCl');
if (video.length == 0)
return false;
video = video[0];
if (mo)
mo.observe(video,
attributes: true
);
setTimeout(() =>
addOrUpdateMediaLink(video.src);
, 50);
return true;
function addOrUpdateMediaLink(src)
console.log(`src: $src`);
let a = document.getElementsByClassName('_open_');
if (a.length == 0)
a = document.createElement("a");
a.className = "_open_";
a.innerHTML = 'Open in new tab';
a.target = "_blank";
// media container
document.getElementsByClassName("_97aPb")[0].appendChild(a);
else
a = a[0];
a.href = src;
createMediaLink();
I don't write javascript too often so this is the best I can do but I'm pretty sure this can still be improved. What do you think?
javascript ecmascript-6 instagram
I've been using the InstagramPhotoLink extension for Opera for some time but instagram broke it recently. I thought I could try to fix it... and I did.
The original extension is rather limited and it supports only a link to the first image and no videos so while fixing it I completely rewrote it in order to extend it.
It works by looking for an image
or video
element with a specific class
and extracts the src
attribute from it and puts it in a new a
-element inside the media-container.
Switching images/videos is supported by the MutationObserver
that updates the links when either a div
or an attribute changes.
I came across a problem where the MutatorObserver
reacts too quickly and before the src
attribute of the new image is set. I solved it by adding a small delay by adding a call to setTimeout
to wait until everything is updated.
function createMediaLink()
function addOrUpdateImageLink(mo)
let image = document.getElementsByClassName('FFVAD');
if (image.length == 0)
return false;
image = image[0];
if (mo)
// the nearest div to the image that stays there when switching images
var div = document.getElementsByClassName("rQDP3");
mo.observe(div[0],
childList: true
);
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
return true;
function addOrUpdateVideoLink(mo)
let video = document.getElementsByClassName('tWeCl');
if (video.length == 0)
return false;
video = video[0];
if (mo)
mo.observe(video,
attributes: true
);
setTimeout(() =>
addOrUpdateMediaLink(video.src);
, 50);
return true;
function addOrUpdateMediaLink(src)
console.log(`src: $src`);
let a = document.getElementsByClassName('_open_');
if (a.length == 0)
a = document.createElement("a");
a.className = "_open_";
a.innerHTML = 'Open in new tab';
a.target = "_blank";
// media container
document.getElementsByClassName("_97aPb")[0].appendChild(a);
else
a = a[0];
a.href = src;
createMediaLink();
I don't write javascript too often so this is the best I can do but I'm pretty sure this can still be improved. What do you think?
javascript ecmascript-6 instagram
edited Jun 11 at 17:06
Sam Onela
5,76961543
5,76961543
asked Jun 9 at 15:21
t3chb0t
31.9k54195
31.9k54195
Do you use this when viewing a list of images/videos and/or when viewing a single item (and navigating through a collection - e.g. using left/right clicks/arrow key presses)?
â Sam Onela
Jun 11 at 4:20
@SamOnela this works only in single item view, not lists.
â t3chb0t
Jun 11 at 4:23
Okay - I am trying to see the linevar div = document.getElementsByClassName("rQDP3");
working... if I go to the album view cats_of_instagram I don't see any results there, then if I click on an item, it opens the modal but I still don't see any results there... if I refresh the item is displayed but not in a modal. When do you see results for that?
â Sam Onela
Jun 11 at 16:01
@SamOnela try this class name_97aPb
- this seems to be a more common one that works on any page. I see that the one I used in my question applies only to certain pages :-|
â t3chb0t
Jun 11 at 16:12
add a comment |Â
Do you use this when viewing a list of images/videos and/or when viewing a single item (and navigating through a collection - e.g. using left/right clicks/arrow key presses)?
â Sam Onela
Jun 11 at 4:20
@SamOnela this works only in single item view, not lists.
â t3chb0t
Jun 11 at 4:23
Okay - I am trying to see the linevar div = document.getElementsByClassName("rQDP3");
working... if I go to the album view cats_of_instagram I don't see any results there, then if I click on an item, it opens the modal but I still don't see any results there... if I refresh the item is displayed but not in a modal. When do you see results for that?
â Sam Onela
Jun 11 at 16:01
@SamOnela try this class name_97aPb
- this seems to be a more common one that works on any page. I see that the one I used in my question applies only to certain pages :-|
â t3chb0t
Jun 11 at 16:12
Do you use this when viewing a list of images/videos and/or when viewing a single item (and navigating through a collection - e.g. using left/right clicks/arrow key presses)?
â Sam Onela
Jun 11 at 4:20
Do you use this when viewing a list of images/videos and/or when viewing a single item (and navigating through a collection - e.g. using left/right clicks/arrow key presses)?
â Sam Onela
Jun 11 at 4:20
@SamOnela this works only in single item view, not lists.
â t3chb0t
Jun 11 at 4:23
@SamOnela this works only in single item view, not lists.
â t3chb0t
Jun 11 at 4:23
Okay - I am trying to see the line
var div = document.getElementsByClassName("rQDP3");
working... if I go to the album view cats_of_instagram I don't see any results there, then if I click on an item, it opens the modal but I still don't see any results there... if I refresh the item is displayed but not in a modal. When do you see results for that?â Sam Onela
Jun 11 at 16:01
Okay - I am trying to see the line
var div = document.getElementsByClassName("rQDP3");
working... if I go to the album view cats_of_instagram I don't see any results there, then if I click on an item, it opens the modal but I still don't see any results there... if I refresh the item is displayed but not in a modal. When do you see results for that?â Sam Onela
Jun 11 at 16:01
@SamOnela try this class name
_97aPb
- this seems to be a more common one that works on any page. I see that the one I used in my question applies only to certain pages :-|â t3chb0t
Jun 11 at 16:12
@SamOnela try this class name
_97aPb
- this seems to be a more common one that works on any page. I see that the one I used in my question applies only to certain pages :-|â t3chb0t
Jun 11 at 16:12
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
4
down vote
accepted
addOrUpdateImageLink()
andaddOrUpdateVideoLink()
are essentially the same, therefore it would be better to create just one function that would accept different parameters dependent on whether our media is an image or video;- In
createMediaLink()
you invokeaddOrUpdateâ¦â¦â¦Link()
functions before you declare them. It is not wrong, but it worsens readability and code flow; - Setting 50 ms delay is not the best way to achieve what you are trying to do. Since I don't know how the DOM workings look like, I left it unchanged though;
- Use strict equality operator (
===
) wherever possible â it performs no type conversion; - Once you pick which quotes you use (
''
or""
), stick to it. Generally, single quotes option is more popular and standard.
Rewrite
const addOrUpdateMediaLink = src =>
if (!src) return;
console.log(`src: $src`);
let a = document.querySelector('._open_');
if (!a)
a = document.createElement('a');
[a.className, a.textContent, a.target] = ['_open_', 'Open in new tab', '_blank'];
// media container
document.querySelector('._97aPb').appendChild(a);
a.href = src;
;
const addOrUpdate = (selector, observeSelector, attr, mo) =>
let media = document.querySelector(selector);
if (!media) return false;
if (mo)
const obj = ;
obj[attr] = true;
mo.observe(document.querySelector(observeSelector), obj);
setTimeout(() => addOrUpdateMediaLink(media.src), 50);
return true;
;
const createMediaLink = () => ;
createMediaLink();
1
wow, this looks awsome! I hadn't thought there would be possbile so many tricks :-)
â t3chb0t
Jun 9 at 17:40
1
The50ms
is just a small randomly picked number because without it the link was often empty when you switched to the next image because instagram is rebuilding an element tree that wasn't always complete.
â t3chb0t
Jun 9 at 17:42
1
I had to make one fix. This didn't workreturn addOrUpdate(mo, ...params);
so I changed it toreturn addOrUpdate(mo, ...selectors['img'], 'childList') || addOrUpdate(mo, ...selectors['video'], 'attributes');
- but maybe it's just me who isn't entirely understanding the new syntax yet because in order to learn it didn't just copy paste it but wrote it on my own so I might have made a mistake somewhere ;-)
â t3chb0t
Jun 9 at 18:47
Yeah, I was in a hurry when I wrote this. Now, after giving it one more second, I better understood what's going on. I've updated the code in my answer.
â Przemek
Jun 10 at 13:21
add a comment |Â
up vote
1
down vote
As is evidenced by the original version of the extension being broken by the HTML update, one drawback of this type of code is that it is brittle. Instagram could update the HTML of their site at anytime, leaving the extension broken. A different approach might be wise. For example, the code could look for video elements - while it is possible to have more than one on a page, the Instagram pages that I looked at appear to either only have one or no video elements. If there are none, then look at the images. Obviously there will likely be more than one image on the page (since the logo and other icons will be present). I'm not sure what the best approach to find the image in focus (maybe see if it has a parent element that is the <article>
element, though that also would be coupled to the structure) but I guess one could look for the image with the largest dimensions.
But if you want to stick with the current approach, the rewritten code in Przemek's answer looks more succint and uniform with ecmascript-6. There are a few other suggestions below that might improve things.
You could use an IIFE to wrap all the code up. While the extension cannot use variables or functions defined by web pages or by other content scripts1, it would be a good practice not to add functions that could have the same name as one in the original source code. While it would be unlikely that the Instagram scripts would have a function called createMediaLink
, it is possible. And it could also be used to inject certain global variables- e.g. document
, window
.
;(doc =>
//addOrUpdateMediaLink, etc.
//contents from crateMediaLink,
)(document);
The function passed to setTimeout could be a partial-function, which would eliminate the extra function call. For example, the following block from addOrUpdateImageLink
:
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
Could be simplified like this:
setTimeout(addOrUpdateMediaLink.bind(null, image.src), 50);
Cool magic, right? (â©ï½Â-ô)âÂÂâÂÂâÂÂï¾Â.*・。ï¾Â
Inside addOrUpdateImageLink
there is a new variable created:
var div = document.getElementsByClassName("rQDP3");
Some JS purists might argue that const
should be used instead of var
, since that is never re-assigned. And also, the naming might be a little misleading, since that function returns an HTMLCollection, so divs
would be more appropraite. The same is true for let image = document.getElementsByClassName('FFVAD');
in addOrUpdateImageLink()
- since multiple elements are returned images
would be more appropriate.
1https://dev.opera.com/extensions/content-scripts/
Even more magic! But I love it and the links will make the study easier :-)
â t3chb0t
Jun 11 at 18:20
The idea with injecting global variable is nice but unfortuantelly extensions are running in a sendbox and they don't have access to any custom javascript variables e.g. on thewindow
object so even when injected like in your example it's not possible to pass them to the script :-( there is one very usefulwindow._sharedData
that contains all theblob:
viedeo links but the extension does not see it.
â t3chb0t
Jun 13 at 16:09
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
accepted
addOrUpdateImageLink()
andaddOrUpdateVideoLink()
are essentially the same, therefore it would be better to create just one function that would accept different parameters dependent on whether our media is an image or video;- In
createMediaLink()
you invokeaddOrUpdateâ¦â¦â¦Link()
functions before you declare them. It is not wrong, but it worsens readability and code flow; - Setting 50 ms delay is not the best way to achieve what you are trying to do. Since I don't know how the DOM workings look like, I left it unchanged though;
- Use strict equality operator (
===
) wherever possible â it performs no type conversion; - Once you pick which quotes you use (
''
or""
), stick to it. Generally, single quotes option is more popular and standard.
Rewrite
const addOrUpdateMediaLink = src =>
if (!src) return;
console.log(`src: $src`);
let a = document.querySelector('._open_');
if (!a)
a = document.createElement('a');
[a.className, a.textContent, a.target] = ['_open_', 'Open in new tab', '_blank'];
// media container
document.querySelector('._97aPb').appendChild(a);
a.href = src;
;
const addOrUpdate = (selector, observeSelector, attr, mo) =>
let media = document.querySelector(selector);
if (!media) return false;
if (mo)
const obj = ;
obj[attr] = true;
mo.observe(document.querySelector(observeSelector), obj);
setTimeout(() => addOrUpdateMediaLink(media.src), 50);
return true;
;
const createMediaLink = () => ;
createMediaLink();
1
wow, this looks awsome! I hadn't thought there would be possbile so many tricks :-)
â t3chb0t
Jun 9 at 17:40
1
The50ms
is just a small randomly picked number because without it the link was often empty when you switched to the next image because instagram is rebuilding an element tree that wasn't always complete.
â t3chb0t
Jun 9 at 17:42
1
I had to make one fix. This didn't workreturn addOrUpdate(mo, ...params);
so I changed it toreturn addOrUpdate(mo, ...selectors['img'], 'childList') || addOrUpdate(mo, ...selectors['video'], 'attributes');
- but maybe it's just me who isn't entirely understanding the new syntax yet because in order to learn it didn't just copy paste it but wrote it on my own so I might have made a mistake somewhere ;-)
â t3chb0t
Jun 9 at 18:47
Yeah, I was in a hurry when I wrote this. Now, after giving it one more second, I better understood what's going on. I've updated the code in my answer.
â Przemek
Jun 10 at 13:21
add a comment |Â
up vote
4
down vote
accepted
addOrUpdateImageLink()
andaddOrUpdateVideoLink()
are essentially the same, therefore it would be better to create just one function that would accept different parameters dependent on whether our media is an image or video;- In
createMediaLink()
you invokeaddOrUpdateâ¦â¦â¦Link()
functions before you declare them. It is not wrong, but it worsens readability and code flow; - Setting 50 ms delay is not the best way to achieve what you are trying to do. Since I don't know how the DOM workings look like, I left it unchanged though;
- Use strict equality operator (
===
) wherever possible â it performs no type conversion; - Once you pick which quotes you use (
''
or""
), stick to it. Generally, single quotes option is more popular and standard.
Rewrite
const addOrUpdateMediaLink = src =>
if (!src) return;
console.log(`src: $src`);
let a = document.querySelector('._open_');
if (!a)
a = document.createElement('a');
[a.className, a.textContent, a.target] = ['_open_', 'Open in new tab', '_blank'];
// media container
document.querySelector('._97aPb').appendChild(a);
a.href = src;
;
const addOrUpdate = (selector, observeSelector, attr, mo) =>
let media = document.querySelector(selector);
if (!media) return false;
if (mo)
const obj = ;
obj[attr] = true;
mo.observe(document.querySelector(observeSelector), obj);
setTimeout(() => addOrUpdateMediaLink(media.src), 50);
return true;
;
const createMediaLink = () => ;
createMediaLink();
1
wow, this looks awsome! I hadn't thought there would be possbile so many tricks :-)
â t3chb0t
Jun 9 at 17:40
1
The50ms
is just a small randomly picked number because without it the link was often empty when you switched to the next image because instagram is rebuilding an element tree that wasn't always complete.
â t3chb0t
Jun 9 at 17:42
1
I had to make one fix. This didn't workreturn addOrUpdate(mo, ...params);
so I changed it toreturn addOrUpdate(mo, ...selectors['img'], 'childList') || addOrUpdate(mo, ...selectors['video'], 'attributes');
- but maybe it's just me who isn't entirely understanding the new syntax yet because in order to learn it didn't just copy paste it but wrote it on my own so I might have made a mistake somewhere ;-)
â t3chb0t
Jun 9 at 18:47
Yeah, I was in a hurry when I wrote this. Now, after giving it one more second, I better understood what's going on. I've updated the code in my answer.
â Przemek
Jun 10 at 13:21
add a comment |Â
up vote
4
down vote
accepted
up vote
4
down vote
accepted
addOrUpdateImageLink()
andaddOrUpdateVideoLink()
are essentially the same, therefore it would be better to create just one function that would accept different parameters dependent on whether our media is an image or video;- In
createMediaLink()
you invokeaddOrUpdateâ¦â¦â¦Link()
functions before you declare them. It is not wrong, but it worsens readability and code flow; - Setting 50 ms delay is not the best way to achieve what you are trying to do. Since I don't know how the DOM workings look like, I left it unchanged though;
- Use strict equality operator (
===
) wherever possible â it performs no type conversion; - Once you pick which quotes you use (
''
or""
), stick to it. Generally, single quotes option is more popular and standard.
Rewrite
const addOrUpdateMediaLink = src =>
if (!src) return;
console.log(`src: $src`);
let a = document.querySelector('._open_');
if (!a)
a = document.createElement('a');
[a.className, a.textContent, a.target] = ['_open_', 'Open in new tab', '_blank'];
// media container
document.querySelector('._97aPb').appendChild(a);
a.href = src;
;
const addOrUpdate = (selector, observeSelector, attr, mo) =>
let media = document.querySelector(selector);
if (!media) return false;
if (mo)
const obj = ;
obj[attr] = true;
mo.observe(document.querySelector(observeSelector), obj);
setTimeout(() => addOrUpdateMediaLink(media.src), 50);
return true;
;
const createMediaLink = () => ;
createMediaLink();
addOrUpdateImageLink()
andaddOrUpdateVideoLink()
are essentially the same, therefore it would be better to create just one function that would accept different parameters dependent on whether our media is an image or video;- In
createMediaLink()
you invokeaddOrUpdateâ¦â¦â¦Link()
functions before you declare them. It is not wrong, but it worsens readability and code flow; - Setting 50 ms delay is not the best way to achieve what you are trying to do. Since I don't know how the DOM workings look like, I left it unchanged though;
- Use strict equality operator (
===
) wherever possible â it performs no type conversion; - Once you pick which quotes you use (
''
or""
), stick to it. Generally, single quotes option is more popular and standard.
Rewrite
const addOrUpdateMediaLink = src =>
if (!src) return;
console.log(`src: $src`);
let a = document.querySelector('._open_');
if (!a)
a = document.createElement('a');
[a.className, a.textContent, a.target] = ['_open_', 'Open in new tab', '_blank'];
// media container
document.querySelector('._97aPb').appendChild(a);
a.href = src;
;
const addOrUpdate = (selector, observeSelector, attr, mo) =>
let media = document.querySelector(selector);
if (!media) return false;
if (mo)
const obj = ;
obj[attr] = true;
mo.observe(document.querySelector(observeSelector), obj);
setTimeout(() => addOrUpdateMediaLink(media.src), 50);
return true;
;
const createMediaLink = () => ;
createMediaLink();
edited Jun 10 at 13:22
answered Jun 9 at 17:06
Przemek
1,032213
1,032213
1
wow, this looks awsome! I hadn't thought there would be possbile so many tricks :-)
â t3chb0t
Jun 9 at 17:40
1
The50ms
is just a small randomly picked number because without it the link was often empty when you switched to the next image because instagram is rebuilding an element tree that wasn't always complete.
â t3chb0t
Jun 9 at 17:42
1
I had to make one fix. This didn't workreturn addOrUpdate(mo, ...params);
so I changed it toreturn addOrUpdate(mo, ...selectors['img'], 'childList') || addOrUpdate(mo, ...selectors['video'], 'attributes');
- but maybe it's just me who isn't entirely understanding the new syntax yet because in order to learn it didn't just copy paste it but wrote it on my own so I might have made a mistake somewhere ;-)
â t3chb0t
Jun 9 at 18:47
Yeah, I was in a hurry when I wrote this. Now, after giving it one more second, I better understood what's going on. I've updated the code in my answer.
â Przemek
Jun 10 at 13:21
add a comment |Â
1
wow, this looks awsome! I hadn't thought there would be possbile so many tricks :-)
â t3chb0t
Jun 9 at 17:40
1
The50ms
is just a small randomly picked number because without it the link was often empty when you switched to the next image because instagram is rebuilding an element tree that wasn't always complete.
â t3chb0t
Jun 9 at 17:42
1
I had to make one fix. This didn't workreturn addOrUpdate(mo, ...params);
so I changed it toreturn addOrUpdate(mo, ...selectors['img'], 'childList') || addOrUpdate(mo, ...selectors['video'], 'attributes');
- but maybe it's just me who isn't entirely understanding the new syntax yet because in order to learn it didn't just copy paste it but wrote it on my own so I might have made a mistake somewhere ;-)
â t3chb0t
Jun 9 at 18:47
Yeah, I was in a hurry when I wrote this. Now, after giving it one more second, I better understood what's going on. I've updated the code in my answer.
â Przemek
Jun 10 at 13:21
1
1
wow, this looks awsome! I hadn't thought there would be possbile so many tricks :-)
â t3chb0t
Jun 9 at 17:40
wow, this looks awsome! I hadn't thought there would be possbile so many tricks :-)
â t3chb0t
Jun 9 at 17:40
1
1
The
50ms
is just a small randomly picked number because without it the link was often empty when you switched to the next image because instagram is rebuilding an element tree that wasn't always complete.â t3chb0t
Jun 9 at 17:42
The
50ms
is just a small randomly picked number because without it the link was often empty when you switched to the next image because instagram is rebuilding an element tree that wasn't always complete.â t3chb0t
Jun 9 at 17:42
1
1
I had to make one fix. This didn't work
return addOrUpdate(mo, ...params);
so I changed it to return addOrUpdate(mo, ...selectors['img'], 'childList') || addOrUpdate(mo, ...selectors['video'], 'attributes');
- but maybe it's just me who isn't entirely understanding the new syntax yet because in order to learn it didn't just copy paste it but wrote it on my own so I might have made a mistake somewhere ;-)â t3chb0t
Jun 9 at 18:47
I had to make one fix. This didn't work
return addOrUpdate(mo, ...params);
so I changed it to return addOrUpdate(mo, ...selectors['img'], 'childList') || addOrUpdate(mo, ...selectors['video'], 'attributes');
- but maybe it's just me who isn't entirely understanding the new syntax yet because in order to learn it didn't just copy paste it but wrote it on my own so I might have made a mistake somewhere ;-)â t3chb0t
Jun 9 at 18:47
Yeah, I was in a hurry when I wrote this. Now, after giving it one more second, I better understood what's going on. I've updated the code in my answer.
â Przemek
Jun 10 at 13:21
Yeah, I was in a hurry when I wrote this. Now, after giving it one more second, I better understood what's going on. I've updated the code in my answer.
â Przemek
Jun 10 at 13:21
add a comment |Â
up vote
1
down vote
As is evidenced by the original version of the extension being broken by the HTML update, one drawback of this type of code is that it is brittle. Instagram could update the HTML of their site at anytime, leaving the extension broken. A different approach might be wise. For example, the code could look for video elements - while it is possible to have more than one on a page, the Instagram pages that I looked at appear to either only have one or no video elements. If there are none, then look at the images. Obviously there will likely be more than one image on the page (since the logo and other icons will be present). I'm not sure what the best approach to find the image in focus (maybe see if it has a parent element that is the <article>
element, though that also would be coupled to the structure) but I guess one could look for the image with the largest dimensions.
But if you want to stick with the current approach, the rewritten code in Przemek's answer looks more succint and uniform with ecmascript-6. There are a few other suggestions below that might improve things.
You could use an IIFE to wrap all the code up. While the extension cannot use variables or functions defined by web pages or by other content scripts1, it would be a good practice not to add functions that could have the same name as one in the original source code. While it would be unlikely that the Instagram scripts would have a function called createMediaLink
, it is possible. And it could also be used to inject certain global variables- e.g. document
, window
.
;(doc =>
//addOrUpdateMediaLink, etc.
//contents from crateMediaLink,
)(document);
The function passed to setTimeout could be a partial-function, which would eliminate the extra function call. For example, the following block from addOrUpdateImageLink
:
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
Could be simplified like this:
setTimeout(addOrUpdateMediaLink.bind(null, image.src), 50);
Cool magic, right? (â©ï½Â-ô)âÂÂâÂÂâÂÂï¾Â.*・。ï¾Â
Inside addOrUpdateImageLink
there is a new variable created:
var div = document.getElementsByClassName("rQDP3");
Some JS purists might argue that const
should be used instead of var
, since that is never re-assigned. And also, the naming might be a little misleading, since that function returns an HTMLCollection, so divs
would be more appropraite. The same is true for let image = document.getElementsByClassName('FFVAD');
in addOrUpdateImageLink()
- since multiple elements are returned images
would be more appropriate.
1https://dev.opera.com/extensions/content-scripts/
Even more magic! But I love it and the links will make the study easier :-)
â t3chb0t
Jun 11 at 18:20
The idea with injecting global variable is nice but unfortuantelly extensions are running in a sendbox and they don't have access to any custom javascript variables e.g. on thewindow
object so even when injected like in your example it's not possible to pass them to the script :-( there is one very usefulwindow._sharedData
that contains all theblob:
viedeo links but the extension does not see it.
â t3chb0t
Jun 13 at 16:09
add a comment |Â
up vote
1
down vote
As is evidenced by the original version of the extension being broken by the HTML update, one drawback of this type of code is that it is brittle. Instagram could update the HTML of their site at anytime, leaving the extension broken. A different approach might be wise. For example, the code could look for video elements - while it is possible to have more than one on a page, the Instagram pages that I looked at appear to either only have one or no video elements. If there are none, then look at the images. Obviously there will likely be more than one image on the page (since the logo and other icons will be present). I'm not sure what the best approach to find the image in focus (maybe see if it has a parent element that is the <article>
element, though that also would be coupled to the structure) but I guess one could look for the image with the largest dimensions.
But if you want to stick with the current approach, the rewritten code in Przemek's answer looks more succint and uniform with ecmascript-6. There are a few other suggestions below that might improve things.
You could use an IIFE to wrap all the code up. While the extension cannot use variables or functions defined by web pages or by other content scripts1, it would be a good practice not to add functions that could have the same name as one in the original source code. While it would be unlikely that the Instagram scripts would have a function called createMediaLink
, it is possible. And it could also be used to inject certain global variables- e.g. document
, window
.
;(doc =>
//addOrUpdateMediaLink, etc.
//contents from crateMediaLink,
)(document);
The function passed to setTimeout could be a partial-function, which would eliminate the extra function call. For example, the following block from addOrUpdateImageLink
:
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
Could be simplified like this:
setTimeout(addOrUpdateMediaLink.bind(null, image.src), 50);
Cool magic, right? (â©ï½Â-ô)âÂÂâÂÂâÂÂï¾Â.*・。ï¾Â
Inside addOrUpdateImageLink
there is a new variable created:
var div = document.getElementsByClassName("rQDP3");
Some JS purists might argue that const
should be used instead of var
, since that is never re-assigned. And also, the naming might be a little misleading, since that function returns an HTMLCollection, so divs
would be more appropraite. The same is true for let image = document.getElementsByClassName('FFVAD');
in addOrUpdateImageLink()
- since multiple elements are returned images
would be more appropriate.
1https://dev.opera.com/extensions/content-scripts/
Even more magic! But I love it and the links will make the study easier :-)
â t3chb0t
Jun 11 at 18:20
The idea with injecting global variable is nice but unfortuantelly extensions are running in a sendbox and they don't have access to any custom javascript variables e.g. on thewindow
object so even when injected like in your example it's not possible to pass them to the script :-( there is one very usefulwindow._sharedData
that contains all theblob:
viedeo links but the extension does not see it.
â t3chb0t
Jun 13 at 16:09
add a comment |Â
up vote
1
down vote
up vote
1
down vote
As is evidenced by the original version of the extension being broken by the HTML update, one drawback of this type of code is that it is brittle. Instagram could update the HTML of their site at anytime, leaving the extension broken. A different approach might be wise. For example, the code could look for video elements - while it is possible to have more than one on a page, the Instagram pages that I looked at appear to either only have one or no video elements. If there are none, then look at the images. Obviously there will likely be more than one image on the page (since the logo and other icons will be present). I'm not sure what the best approach to find the image in focus (maybe see if it has a parent element that is the <article>
element, though that also would be coupled to the structure) but I guess one could look for the image with the largest dimensions.
But if you want to stick with the current approach, the rewritten code in Przemek's answer looks more succint and uniform with ecmascript-6. There are a few other suggestions below that might improve things.
You could use an IIFE to wrap all the code up. While the extension cannot use variables or functions defined by web pages or by other content scripts1, it would be a good practice not to add functions that could have the same name as one in the original source code. While it would be unlikely that the Instagram scripts would have a function called createMediaLink
, it is possible. And it could also be used to inject certain global variables- e.g. document
, window
.
;(doc =>
//addOrUpdateMediaLink, etc.
//contents from crateMediaLink,
)(document);
The function passed to setTimeout could be a partial-function, which would eliminate the extra function call. For example, the following block from addOrUpdateImageLink
:
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
Could be simplified like this:
setTimeout(addOrUpdateMediaLink.bind(null, image.src), 50);
Cool magic, right? (â©ï½Â-ô)âÂÂâÂÂâÂÂï¾Â.*・。ï¾Â
Inside addOrUpdateImageLink
there is a new variable created:
var div = document.getElementsByClassName("rQDP3");
Some JS purists might argue that const
should be used instead of var
, since that is never re-assigned. And also, the naming might be a little misleading, since that function returns an HTMLCollection, so divs
would be more appropraite. The same is true for let image = document.getElementsByClassName('FFVAD');
in addOrUpdateImageLink()
- since multiple elements are returned images
would be more appropriate.
1https://dev.opera.com/extensions/content-scripts/
As is evidenced by the original version of the extension being broken by the HTML update, one drawback of this type of code is that it is brittle. Instagram could update the HTML of their site at anytime, leaving the extension broken. A different approach might be wise. For example, the code could look for video elements - while it is possible to have more than one on a page, the Instagram pages that I looked at appear to either only have one or no video elements. If there are none, then look at the images. Obviously there will likely be more than one image on the page (since the logo and other icons will be present). I'm not sure what the best approach to find the image in focus (maybe see if it has a parent element that is the <article>
element, though that also would be coupled to the structure) but I guess one could look for the image with the largest dimensions.
But if you want to stick with the current approach, the rewritten code in Przemek's answer looks more succint and uniform with ecmascript-6. There are a few other suggestions below that might improve things.
You could use an IIFE to wrap all the code up. While the extension cannot use variables or functions defined by web pages or by other content scripts1, it would be a good practice not to add functions that could have the same name as one in the original source code. While it would be unlikely that the Instagram scripts would have a function called createMediaLink
, it is possible. And it could also be used to inject certain global variables- e.g. document
, window
.
;(doc =>
//addOrUpdateMediaLink, etc.
//contents from crateMediaLink,
)(document);
The function passed to setTimeout could be a partial-function, which would eliminate the extra function call. For example, the following block from addOrUpdateImageLink
:
setTimeout(() =>
addOrUpdateMediaLink(image.src);
, 50);
Could be simplified like this:
setTimeout(addOrUpdateMediaLink.bind(null, image.src), 50);
Cool magic, right? (â©ï½Â-ô)âÂÂâÂÂâÂÂï¾Â.*・。ï¾Â
Inside addOrUpdateImageLink
there is a new variable created:
var div = document.getElementsByClassName("rQDP3");
Some JS purists might argue that const
should be used instead of var
, since that is never re-assigned. And also, the naming might be a little misleading, since that function returns an HTMLCollection, so divs
would be more appropraite. The same is true for let image = document.getElementsByClassName('FFVAD');
in addOrUpdateImageLink()
- since multiple elements are returned images
would be more appropriate.
1https://dev.opera.com/extensions/content-scripts/
edited Jun 11 at 18:25
answered Jun 11 at 17:12
Sam Onela
5,76961543
5,76961543
Even more magic! But I love it and the links will make the study easier :-)
â t3chb0t
Jun 11 at 18:20
The idea with injecting global variable is nice but unfortuantelly extensions are running in a sendbox and they don't have access to any custom javascript variables e.g. on thewindow
object so even when injected like in your example it's not possible to pass them to the script :-( there is one very usefulwindow._sharedData
that contains all theblob:
viedeo links but the extension does not see it.
â t3chb0t
Jun 13 at 16:09
add a comment |Â
Even more magic! But I love it and the links will make the study easier :-)
â t3chb0t
Jun 11 at 18:20
The idea with injecting global variable is nice but unfortuantelly extensions are running in a sendbox and they don't have access to any custom javascript variables e.g. on thewindow
object so even when injected like in your example it's not possible to pass them to the script :-( there is one very usefulwindow._sharedData
that contains all theblob:
viedeo links but the extension does not see it.
â t3chb0t
Jun 13 at 16:09
Even more magic! But I love it and the links will make the study easier :-)
â t3chb0t
Jun 11 at 18:20
Even more magic! But I love it and the links will make the study easier :-)
â t3chb0t
Jun 11 at 18:20
The idea with injecting global variable is nice but unfortuantelly extensions are running in a sendbox and they don't have access to any custom javascript variables e.g. on the
window
object so even when injected like in your example it's not possible to pass them to the script :-( there is one very useful window._sharedData
that contains all the blob:
viedeo links but the extension does not see it.â t3chb0t
Jun 13 at 16:09
The idea with injecting global variable is nice but unfortuantelly extensions are running in a sendbox and they don't have access to any custom javascript variables e.g. on the
window
object so even when injected like in your example it's not possible to pass them to the script :-( there is one very useful window._sharedData
that contains all the blob:
viedeo links but the extension does not see it.â t3chb0t
Jun 13 at 16:09
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196163%2fcreating-and-updating-link-to-instagram-image-or-video%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Do you use this when viewing a list of images/videos and/or when viewing a single item (and navigating through a collection - e.g. using left/right clicks/arrow key presses)?
â Sam Onela
Jun 11 at 4:20
@SamOnela this works only in single item view, not lists.
â t3chb0t
Jun 11 at 4:23
Okay - I am trying to see the line
var div = document.getElementsByClassName("rQDP3");
working... if I go to the album view cats_of_instagram I don't see any results there, then if I click on an item, it opens the modal but I still don't see any results there... if I refresh the item is displayed but not in a modal. When do you see results for that?â Sam Onela
Jun 11 at 16:01
@SamOnela try this class name
_97aPb
- this seems to be a more common one that works on any page. I see that the one I used in my question applies only to certain pages :-|â t3chb0t
Jun 11 at 16:12