Discuss Scratch

IcyCoder
Scratcher
1000+ posts

Userscript Help Needed

My userscript I made for my school because we use slack and the redirect part of it is blocked at my school so this userscript is supposed to make links not have to redirect by making the onclick but it is not working

// ==UserScript==
// @name Fix Slack
// @include https://*.slack.com/*
// ==/UserScript==

document.getElementsByTagName("body").onload=function(){
document.getElementsByTagName("a")[0].removeAttribute("onclick");
};

The problem is that it does nothing for some reason.

I also tried this:

// ==UserScript==
// @name Fix Slack
// @include https://*.slack.com/*
// ==/UserScript==

document.getElementsByTagName("a").onload=function(){
document.getElementsByTagName("a")[0].removeAttribute("onclick");
};

Please tell me what I am doing wrong… Thanks!

Last edited by IcyCoder (Sept. 21, 2016 19:40:02)


Because JS is the future (echos) future future futur futu fut fu f
kvackkvack
Scratcher
500+ posts

Userscript Help Needed

Look at your code again. You're setting property onload of an array of objects (which in this case happen to all be elements), and an array obviously doesn't trigger onload.
IcyCoder
Scratcher
1000+ posts

Userscript Help Needed

kvackkvack wrote:

Look at your code again. You're setting property onload of an array of objects (which in this case happen to all be elements), and an array obviously doesn't trigger onload.
Sorry I do not really understand
edit: wait you mean I do not need the onload?

Last edited by IcyCoder (Sept. 21, 2016 19:40:52)


Because JS is the future (echos) future future futur futu fut fu f
scratchyone
Scratcher
100+ posts

Userscript Help Needed

What he is saying is that you have an array (link1,link2, etc.). If you set the onload of the array, you are changing the array's property. You need to change the property of each of the elements inside the array.
IcyCoder
Scratcher
1000+ posts

Userscript Help Needed

scratchyone wrote:

What he is saying is that you have an array (link1,link2, etc.). If you set the onload of the array, you are changing the array's property. You need to change the property of each of the elements inside the array.
OHHHHHHHHHH

Because JS is the future (echos) future future futur futu fut fu f
IcyCoder
Scratcher
1000+ posts

Userscript Help Needed

So does this work:

len = document.getElementsByTagName("a").length;
for (i = 0; i < len; i++) {
document.getElementsByTagName("a")[i].removeAttribute("onclick");
}

Because JS is the future (echos) future future futur futu fut fu f
IcyCoder
Scratcher
1000+ posts

Userscript Help Needed

OK so it worked when I put it in the js console but the userscript is not loading

Because JS is the future (echos) future future futur futu fut fu f
Jonathan50
Scratcher
1000+ posts

Userscript Help Needed

You are setting the property “onload” on a list of elements. Which does nothing. Also, you are only modifying the first link on the page.

Try something like
window.onload = function () {
  for (let link of document.getElementsByTagName('a')) {
    link.removeAttribute('onclick');
  }
}
window.onload gets called when the page is finished loading. for (let <variable> of <expression>) <statement> does something for each item in an iterable.

Last edited by Jonathan50 (Sept. 23, 2016 00:13:27)


Not yet a Knight of the Mu Calculus.
jokebookservice1
Scratcher
1000+ posts

Userscript Help Needed

IcyCoder wrote:

OK so it worked when I put it in the js console but the userscript is not loading
1) Check your console for errors
2) Add the line below to the start of the userscript
console.log("I am actually running");
3) If it doesn't run (nothing in the console), maybe change @include to @match
4) Once you find the bug, obviously, undo step 2

Last edited by jokebookservice1 (Sept. 22, 2016 18:47:09)

IcyCoder
Scratcher
1000+ posts

Userscript Help Needed

jokebookservice1 wrote:

IcyCoder wrote:

OK so it worked when I put it in the js console but the userscript is not loading
1) Check your console for errors
2) Add the line below to the start of the userscript
console.log("I am actually running");
3) If it doesn't run (nothing in the console), maybe change @include to @match
4) Once you find the bug, obviously, undo step 2
Thanks!

Because JS is the future (echos) future future futur futu fut fu f
Nanners119
Scratcher
5 posts

Userscript Help Needed

I have been on Scratch for 2 months but 1 year with my old one………………….anyways I wanted to say that people have been mean to me I had to report people a lot (I feel bad for them) I wanted to know if there is a way to fix that?
(answer)
IcyCoder
Scratcher
1000+ posts

Userscript Help Needed

Nanners119 wrote:

I have been on Scratch for 2 months but 1 year with my old one………………….anyways I wanted to say that people have been mean to me I had to report people a lot (I feel bad for them) I wanted to know if there is a way to fix that?
(answer)
You cannot fix people being mean to you but you can contact the scratch team here and they can help you https://scratch.mit.edu/contact-us/

PS this is not the topic for this

Because JS is the future (echos) future future futur futu fut fu f
jokebookservice1
Scratcher
1000+ posts

Userscript Help Needed

Nanners119 wrote:

I have been on Scratch for 2 months but 1 year with my old one………………….anyways I wanted to say that people have been mean to me I had to report people a lot (I feel bad for them) I wanted to know if there is a way to fix that?
(answer)
Unfortunately not

If somebody is mean to you, it is annoying. But just report it, and ignore it. The people who are mean to you are the ones that are wrong.

EDIT: I got out-posted (ninja'd) by IcyCoder

Last edited by jokebookservice1 (Sept. 25, 2016 21:27:16)

Nanners119
Scratcher
5 posts

Userscript Help Needed

jokebookservice1 wrote:

Nanners119 wrote:

I have been on Scratch for 2 months but 1 year with my old one………………….anyways I wanted to say that people have been mean to me I had to report people a lot (I feel bad for them) I wanted to know if there is a way to fix that?
(answer)
Unfortunately not

If somebody is mean to you, it is annoying. But just report it, and ignore it. The people who are mean to you are the ones that are wrong.

EDIT: I got out-posted (ninja'd) by IcyCoder[/quote
okay
move (move on) steps
robinp
Scratcher
100+ posts
NickyNouse
Scratcher
1000+ posts

Userscript Help Needed

Userscripts already run after everything's loaded (well, after every element exists, but before images and things are loaded). You can control this with the @run-at command. Since it runs after everything's loaded, the onload event will never fire again. Just put your code in the body of the script.

Everyone was right about the array* thing too. document.getElementsByTagName(“body”) will return a list of all the elements with the tag name “body” (there happens to only be one). You can access the first element via document.getElementsByTagName(“body”)[0] – although JS has the shortcut document.body built-in.

So all you should need to do is loop through the elements:
var listOfLinks = document.getElementsByTagName('a');
for (let i = 0; i < listOfLinks.length; i++) {
  let link = listOfLinks[i];
  link.removeAttribute('onclick');
}

*almost. Technically a NodeList doesn't inherit from Array so it's missing some of the convenience methods. That's why it's safer to use a traditional for-loop in this situation than a for-of/in loop like @Jonathan50 did. See https://developer.mozilla.org/en-US/docs/Web/API/NodeList for a better explanation.

The next problem is that Slack isn't a static HTML page. The page doesn't load with any of its messages already there, so the previous method won't work. You'll need to fix links as they appear. The best method in this case would be to use a MutationObserver, which lets you run a function whenever a new element is added:

// use a MutationObserver to get rid of the attribute for all future links
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    for(let i = 0; i < mutation.addedNodes.length; i++) {
      let node = mutation.addedNodes[i];
      if(node.tagName == "A") {
        // if the element is a link, remove its onclick
        node.removeAttribute('onclick');
      } else if(node.getElementsByTagName) { // (not all nodes can have children)
      	// mutationObserver only gives us a list of the parents that were created, we need to check each one's children for links as well
      	let childLinks = node.getElementsByTagName("a");
        for(let j = 0; j < childLinks.length; j++) {
          childLink = childLinks[j];
          childLink.removeAttribute('onclick');
        }
      }
    }
  });
});
//search the entire document for links
observer.observe(document.body, {childList: true, subtree: true});

MutationObservers are very hard to work with, and the code would've been a lot shorter if we'd used a timer and lazily searched every element every time. But those techniques are bad for this kind of thing, for reasons I won't get into right now. The above code should do the trick.

Something to watch out for: this removes the onclick attribute from all links on the site, even ones that don't do the redirect thing. I take no responsibility for it breaking buttons and things throughout the Slack website.

Last edited by NickyNouse (Sept. 27, 2016 09:52:43)

IcyCoder
Scratcher
1000+ posts

Userscript Help Needed

NickyNouse wrote:

Userscripts already run after everything's loaded (well, after every element exists, but before images and things are loaded). You can control this with the @run-at command. Since it runs after everything's loaded, the onload event will never fire again. Just put your code in the body of the script.

Everyone was right about the array* thing too. document.getElementsByTagName(“body”) will return a list of all the elements with the tag name “body” (there happens to only be one). You can access the first element via document.getElementsByTagName(“body”)[0] – although JS has the shortcut document.body built-in.

So all you should need to do is loop through the elements:
var listOfLinks = document.getElementsByTagName('a');
for (let i = 0; i < listOfLinks.length; i++) {
  let link = listOfLinks[i];
  link.removeAttribute('onclick');
}

*almost. Technically a NodeList doesn't inherit from Array so it's missing some of the convenience methods. That's why it's safer to use a traditional for-loop in this situation than a for-of/in loop like @Jonathan50 did. See https://developer.mozilla.org/en-US/docs/Web/API/NodeList for a better explanation.

The next problem is that Slack isn't a static HTML page. The page doesn't load with any of its messages already there, so the previous method won't work. You'll need to fix links as they appear. The best method in this case would be to use a MutationObserver, which lets you run a function whenever a new element is added:

// use a MutationObserver to get rid of the attribute for all future links
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    for(let i = 0; i < mutation.addedNodes.length; i++) {
      let node = mutation.addedNodes[i];
      if(node.tagName == "A") {
        // if the element is a link, remove its onclick
        node.removeAttribute('onclick');
      } else if(node.getElementsByTagName) { // (not all nodes can have children)
      	// mutationObserver only gives us a list of the parents that were created, we need to check each one's children for links as well
      	let childLinks = node.getElementsByTagName("a");
        for(let j = 0; j < childLinks.length; j++) {
          childLink = childLinks[j];
          childLink.removeAttribute('onclick');
        }
      }
    }
  });
});
//search the entire document for links
observer.observe(document.body, {childList: true, subtree: true});

MutationObservers are very hard to work with, and the code would've been a lot shorter if we'd used a timer and lazily searched every element every time. But those techniques are bad for this kind of thing, for reasons I won't get into right now. The above code should do the trick.

Something to watch out for: this removes the onclick attribute from all links on the site, even ones that don't do the redirect thing. I take no responsibility for it breaking buttons and things throughout the Slack website.
Cool thanks for that explanation I will try it soon

Because JS is the future (echos) future future futur futu fut fu f

Powered by DjangoBB