• [HTML/JS] Need help stripping target attribute of anchors on a generated page
    23 replies, posted
So at my job we work with something called Articulate Rise. It's a neat little course creator that's similar to Squarespace, Adobe Spark, etc. where you can click and drag to make courses that are essentially web pages. It's dead simple to use so our team of instructional designers can get a lot done with it with no tech experience. The course is essentially one index page that dynamically loads content and structure as the user goes through it. The shitty thing is that the entire page is obfuscated and generated upon the client loading it (via a JavaScript window.courseData that's like 100,000 characters long and entirely gibberish), so I can't directly edit the webpage other than in the web-based editor prior to exporting it, which is limited (I can't directly edit the HTML in their editor, I can only add/edit pre-made "blocks" and change images/text). The program can export in a web format, which is what we're doing for this particular course. It gives some minified JavaScript, an index page with encrypted course data, all as sets with randomly generated filenames, and some room to inject CSS or JS into the <head> tag if I know what I'm doing. Anyways, my boss wants us to have a bunch of images in a gallery that links to certain sections of the course, like a fancy table of contents. There's no way to link to other parts of the course in this program, as by default it gives you a sidebar and table of contents (that my boss doesn't want as it "wastes space" so we have it turned off). I've injected some CSS to remove some other parts of the page as well. However, the issue I'm running into is that by default all links I make are set to open with target="_blank". This means that if people browse the course every link is going to open in a new tab/window which is a huge issue. My knowledge of JavaScript is basically printing hello world, so I'm struggling to get something to work here. I need to, once the page is fully loaded, find the <a> elements that are children of <p> that are children of <div class="fr-view">, and strip the attribute tag from them (or set them to target=_self"). I don't want to affect any other anchors, just these, as they are the ones that link to other sections of the course and not external content. Right now I've got the following code which doesn't work because I have no idea what I'm doing: <script> window.onload = function (){ var x = document.querySelectorAll('div.fr-view > p > a[target="_blank"]'); var i; for (i = 0; i < x.length; i++) {     x[i].removeAttribute(target); } } </script> I'm not even sure I have the CSS selector right. I've tried the support team at Articulate but they're basically "we'll add this as a feature request" so that's not helping me now. Any help would be appreciated. I can provide more info if needed.
>adds butt loads of js >For two lines to do the same operation Doesn't work like that Target is meant to be a string in your remove attribute to say the least Otherwise this is not that great to debug without knowing your DOM. Running the query selector in the JavaScript console will tell you if it's returning an array of HTMLelements
Well, adding jQuery to the page and trying to make some code, I've got this so far which isn't working for probably obvious-to-everyone-but-me reasons: <head> ... <script type="text/javascript" src="lib/jquery-3.3.1.min.js"></script> ... </head> <body> ... <script> $( document ).ready(function() {  $( "a[target^='https://website.com/subdomain/subdomain/']").on("click", function() {     $(e.currentTarget).removeAttr("target");     })  }); </script> ... </body> It's not working, and me being so totally ignorant of JavaScript I am having trouble understanding basic concepts needed to even work with the language. I don't even really know how to find the function that's forcing target="_blank" to be applied to my links, so all I can think of is changing it after the fact.
I guess I'll try googling a way to do that then. I'm slightly tech savvy so all this kind of stuff gets dumped on my plate at my job, even though I'm totally not trained in it at all :/
https://jsfiddle.net/u87dgr50/ Works for me
The thing is that I can't directly add a class or ID to the HTML since I don't have access to it directly. I know that all the links I need are the child of a <p> element thats the child of a <div> with the class "fr-view" so I can work from there. The original code I made is selecting an array of values at least (document.querySelectorAll('div.fr-view > p > a[target="_blank"]') so I guess now I need it to strip the attribute whenever the page changes or elements are added/removed.
Links would be red if they still contained a blank target https://files.facepunch.com/forum/upload/1755/ff739c59-71c0-47c6-aa2a-5311af26b308/image.png but when I uncomment the line, simple enough https://files.facepunch.com/forum/upload/1755/001ca1da-8739-4f86-a809-5df3132bf46a/image.png
The only thing is I would give "x" a better name, if you start writing variable names with 1 letter you'll soon go back to the code and not know what the hell anything is.
So it's not working for me. When the page loads and I click on the link, it still opens in a new tab. For reference, here's how the index page is laid out, with some info stripped for privacy reasons { <!DOCTYPE html> <html lang="en" class="">   <head>     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">     <meta charset="utf-8">     <title>My Webpage</title>     <link type="text/css" rel="stylesheet" href="lib/icomoon.css">     <link type="text/css" rel="stylesheet" href="lib/main.bundle.css">     <script type="text/javascript" src="lib/player-0.0.11.min.js"></script>     <script type="text/javascript" src="lib/lzwcompress.js"></script>     <!-- Resize Hack -->     <script type="text/javascript">       window.resizeTo(screen.width, screen.height);     </script> /*all stuff that came from the Articulate Rise program*/       <!--[if lt IE 9]>     <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>     <![endif]-->   </head>   <body>     <style>           /*fonts n shit*/     </style>     <div id="app"></div>     <script type="text/javascript">   (function(root) {    /*i think all this code is for label languages etc.*/};     window.courseData = "eyJjb3Vyc2UiOnsidGl0bGUiOiJRdWlubmlwaWFjIFVuaXZlcnNpdHkgfCBPbmxpbmUgUHJvZ3JhbXMgTmV3c2xldHRlciAtIE5vdmVtYmVyIDIwMTgiLCJpZCI6Ik5IVDZRMWI3TzBmYkJtS2FnbUh0cDJETFRRNVFUMnVI /*literally 100,000 characters of gibberish*/";     function isExport() {       return true;     }     function resolvePath(path) {       return ('assets/').concat(path);     }     root.Runtime = {       isExport: isExport,       resolvePath: resolvePath     };   }(window)); </script>     <script src="lib/main.bundle.js"></script> <script> /*my little baby script i'm trying to make*/ </script>   </body> </html>
the pages are dynamically generated by the looks of it. Means that the elements you want to edit don't even exist when the function is being run
In which case you can do addEventListener("load", function() {   // Code here })
Yeah, so I'm not even sure how to change them. Is there some kind of function I can attach, like an event listener or something (I have no clue what the terminology is here)? My knowledge of coding is basic HTM/CSSL so I've never dabbled with JavaScript before. TBH I'd love if my boss would send me to a class or something because I have a feeling I'm going to need to know this stuff in the future.
is this demo page a 1:1 replacant on what you're working on? because the class selectors would indeed be wrong
Have you bought up just how bad an idea it is to have code like this? Like this is painful to read I assume there's some reason you're keeping it like this?
Not OP's fault 👉 https://articulate.com/
Before I detail this, I need to mention my boss is a "I want it this way; find a way to do it, no isn't an option" type of person, and I've tried to explain that this is getting pretty technically complex to make something "pretty" but it's falling on deaf ears. She wants the links to each part of the course as an image gallery, where the user has a bunch of square pictures they can click on to be directed somewhere, rather than simple hyperlinks. Rise doesn't offer a way to make images links, so I'm using the next best thing. There's a flipcard kind of interface where you can click on a square to have it flip over and display text; this text can then have a hyperlink (that I can only give a URL for, I can't add classes, targets, attributes etc.). This is normally used in courses for mini flashcards or knowledge tests. She wants it to be course links. So I have the front of the flipcard be the image, and when they click it it flips over with a descriptive link. This link always opens in a new tab no matter what due to some script during the generation of the page. I found that each course "page" has a static, generated addendum to the URL that depends on various factors, but as long as the course isn't heavily modified every time I export it it will be the same. So, I just take the full URL (because Rise will auto append http to anylink I give, so I can't use a relative link) from that page and use it for the link. Really hacky, but it works. The class for the div that contains the back of the flash card (which has text) is fr-view. Inside that is a paragraph element, and inside that is the link. In that example, there should be a flash card setup with images of fruit I think; that's basically what I'm working with, it just wouldn't have an anchor in the paragraph element. The anchors don't have classes or IDs to work with and I can't add my own. I'm not in the office now but I can try to remove the branding and try to show it better, or take some screenshots. At this point it seems like it'd be easier to just make my own gallery widget in their "Storyline" application and embed it as an iframe, but that's another can of worms.
Update: so it looks like this code is working for the first time the page loads, and affects all the links I need: <script> addEventListener("load", function() { var x = document.querySelectorAll('div.fr-view > p > a[target="_blank"]'); var i; for (i = 0; i < x.length; i++) { x[i].removeAttribute('target'); } }); </script> However, once a user clicks a link (which just dynamically alters the page rather than bringing them somewhere else), the links on the new layout of the page are then unaffected. The same selector works, but the event listener isn't being attached for some reason. I tried using their "Storyline" tool but getting the layout of the images to be responsive to the browser is not going to happen. I might see if I can just embed an iframe or something. I tried to explain this issue to my boss but she's confident I will find a solution, which is aggravating as this is wasting a lot of my time when we could just go with text links and figure this out some other day.
you want something really, REALLY hacky? Put the function behind a setInterval, run it every half a second vv
If the OP doesn't want to try and figure out how to edit the code that's actually generating the page, then the only options really are this, or using a Mutation Observer. Mutation Observers are IE11+, whilst setInterval probably works on anything that runs JavaScript
So, update. I decided "fuck it" and coded my own website based on the style used in Articulate Rise. I couldn't get the animations to transfer over neatly and I didn't want to just rip them and hackily shove it in, but I got some basic functionality in terms of image highlighting, responsive design, etc. that works well enough using Bootstrap to speed things up and some minor styling changes in the CSS. Boss okay'd it since we didn't need SCORM functionality for this particular use case scenario (meaning this won't work for courses that need to send grades back to the LMS) but I told her that this is going to be a hurdle moving forward so please just use the built in sidebar feature that works fine and isn't ugly at all, and she conceded. Since I still need to give the bounty, even though the workaround isn't ideal, I'm gonna give it to Scratch since he posted the most, but I appreciate everyone's help regardless.
Sorry, you need to Log In to post a reply to this thread.