0

Javascript I tried to adapt doesn't work at all. How to make it working?

Problem:In my workplace we have in many paces hyperlinks in which I have to click on them to open the ticket number. But all the ticket numbers are hyperlinked to a new website which is very slow and I don't see that issue getting fixed. There is a old website which is very fast and I want the hyperlinks to direct me there only.

e.g. A Link directs me to

https://companysachinperf.com/newweb/TicketDetnumber.jspx?tNumber=7-12345

But i want that whenever i click on it it direct me to a new links https://oldwebe.company.com/xyz/Ticketnumber.jspx?tNumber=7-12345

Note:

1.Underlying database for both website is same.

2.company.com and oldwebe.comapny are just for explanation purpose.

3.7-12345 is the ticket number in my example, but on a given html page there can be many such tickets and as soon as I click on any of them it old website should open for that ticket number.

4.This is first time I have started coding in Javascript.

Attempted Solution (which is not working). I put this script in Tamper Monkey

var href = "https://companysachinperf.com/newweb/TicketDetnumber.jspx?tNumber=7-12345"
var oldWebsiteLink = "https://oldwebe.company.com/xyz/Ticketnumber.jspx?tNumber=@id"
var elems = document.querySelectorAll('.comp-link');

for (var i=elems.length; i--;) {
    elems[i].addEventListener('click', function(e) {
        e.preventDefault();
        var hrefVal = this.getAttribute('href');
        var id = hrefVal.substr(hrefVal.lastIndexOf('/') + 1);
        var newLink = oldWebsiteLink.replace("@id", id);
        console.log(newLink);
        window.open(newLink,'_blank');

    }, false);
}
Ina Plaksin
  • 157
  • 1
  • 3
Sach
  • 161
  • 2
  • 10
  • Why are you changing link destinations on the front-end, with JavaScript? I'd suggest that this would be better achieved on the back-end, rather than - potentially - sending users to unexpected websites. – David Thomas Dec 08 '18 at 10:10
  • David i want to change it only for me, as i am one of the end users :) , i do not want to change it for others – Sach Dec 08 '18 at 10:11
  • Ah, that makes sense then! Is it possible for you to post some representative HTML that gives an idea of the page structure you're working with? Ideally the 'input'/original HTML and the 'output'/updated HTML you want to end up with? – David Thomas Dec 08 '18 at 10:16
  • David unfortunately not .as i am not that familiar with html as well . What i can mention is page structure is not fixed. The ticket numbers i get is after searching for a keyword, say "incorrect output"(just for e.g.) and the ticket numbers are listed in portion of the webpage. in other sections there are lots of other information related to "incorrect output" . and i want javascript to skip those _other sections_ and just work when i click on any ticket number with hyperlink of the format which i put. – Sach Dec 08 '18 at 10:25
  • David ///So you can say a javascript on action "when i click on that old link" and direct me to new one in a new tab. – Sach Dec 08 '18 at 10:27
  • I dislike the approach of "on a click I want to update the link that I go to" (though obviously that's your prerogative); instead I prefer to simply update all the relevant links so that you know - in advance - where you're going (and can visually assess whether the function works before you end up in the wrong place). So, based on my own preferences, would this meet your requirements: https://jsfiddle.net/davidThomas/nkxa3fu7/5 – David Thomas Dec 08 '18 at 10:35
  • David , conceptually it does meet requirements, i am trying to check exactly to put html , css and javascript to work – Sach Dec 08 '18 at 11:12
  • @David . How to adapt the code that you provided to be flexible for any ticket number. Currently it is hardcoded for 7-12345. Another question, How to put all the html+css+js code all in tamper monkey ? – Sach Dec 09 '18 at 11:22

4 Answers4

3

One approach is the following:

// here we use the Arrow syntax form of an Immediately-Invoked Function
// Expression ('IIFE'); this function is encountered and then immediately
// invoked by the browser:
// (function(){ /*...code...*/ })() or
// (()=>{ /*...code...*/})()
(() => {

  // using document.querySelectorAll('a') to retrieve a NodeList
  // of all <a> elements in the document, and passing that
  // NodeList to Array.from() in order to use Array methods
  // on the discovered Nodes:
  let links = Array.from(document.querySelectorAll('a')),

      // the new path we want to create:
      newPath = '/xyz/Ticketnumber.jspx';

  // here we filter the links Array, again using an Arrow function:
  links.filter(

    // the first argument of the Array.prototype.filter() method
    // is always a reference to the current array-element of the
    // Array (here it's named 'anchor'); and this is passed into
    // the function:
    (anchor) => {

      // if the anchor.hostname is exactly-equal to the supplied
      // String:
      if (anchor.hostname === 'companysachinperf.com') {

        // we update/set the 'data-oldhref' attribute of the
        // current <a> element to the current value of the href
        // attribute (this is for demonstration purposes in the
        // demo, and is irrelevant to the performance/functionality;
        // it can be removed:
        anchor.dataset.oldhref = anchor.href;

        // we update the <a> element's hostname property to the
        // value of the supplied String:
        anchor.hostname = 'oldwebe.company.com';

        // we update the path to the new path:
        anchor.pathname = newPath;
      }
    })
// here we close the function statement, the parentheses that follow
// the function (the '()') can contain any arguments you wish to supply
// and those arguments will be available to the function; however they
// would need to be declared within the opening parentheses of the
// Arrow function:
/*    ((argumentA,argumentB) => {
        ...code...
      })(document.body,somethingElse);
*/
})();

(() => {
  let links = Array.from(document.querySelectorAll('a')),
    newPath = '/xyz/Ticketnumber.jspx';
  links.filter(
    (anchor) => {
      if (anchor.hostname === 'companysachinperf.com') {
        anchor.dataset.oldhref = anchor.href;
        anchor.hostname = 'oldwebe.company.com';
        anchor.pathname = newPath;
      }
    })
})();
/*
  irrelevant to the functionality and for demo purposes only:
*/

a::before {
  content: attr(href);
}

a::after {
  display: block;
  content: '\A(Used to be: ' attr(data-oldhref) ')';
}
<a href="https://companysachinperf.com/newweb/TicketDetnumber.jspx?tNumber=7-12345" data-oldhref=""></a>

JS Fiddle demo.

To wrap the functionality into a Tampermonkey script, from my own installation of Tampermonkey:

// ==UserScript==
// @name         Modifying links
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Modifying links from one hostname to another
// @author       David Thomas: https://stackoverflow.com/a/53693814/82548
// @match        https://companysachinperf.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    (() => {
        let links = Array.from(document.querySelectorAll('a')),
            newPath = '/xyz/Ticketnumber.jspx';
        links.filter(
            (anchor) => {
                if (anchor.hostname === 'companysachinperf.com') {
                    anchor.dataset.oldhref = anchor.href;
                    anchor.hostname = 'oldwebe.company.com';
                    anchor.pathname = newPath;
                }
            })
    })();
})();

From your comment below the question:

How to adapt the code that you provided to be flexible for any ticket number. Currently it is hardcoded for 7-12345. ...How to put all the html+css+js code all in [Tampermonkey]?

No, you're mistaken, while there is only one <a> element in the demo if you look at the code the ticket number, the tNumber=12345 is absolutely not modified or encoded in any way except in the <a> element's href attribute; the supplied code – assuming that link format matches your description – will work with any ticket number, since it will remain unchanged by the script.

As for adding the HTML to Tampermonkey: you don't need to; the Tampermonkey script operates on the HTML it finds in the relevant pages (which you determine using the // @match http://*/* line in the Tampermonkey script).

As for adding CSS to a page using Tampermonkey, that's easy enough, for example:

// ==UserScript==
// @name         Adding Style demo
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world with garish color choices
// @author       David Thomas: https://stackoverflow.com/a/53693814/82548
// @match        https://stackoverflow.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // create a <style> element:
    let style = document.createElement('style'),

        // find the <head> element:
        head = document.querySelector('head'),
        // define a CSS Selector:
        importantElements = 'h1 > a',
        // define a CSS property-value (note that
        // using '!important' - which ordinarily
        // shouldn't be used is used here because
        // I couldn't be bothered to increase the
        // specificity of the 'importantElement'
        // selector):
        importantColor = '#f00 !important';

    // assign an id to the created <style> element:
    style.id = 'TampermonkeyInsertedStyleElement';

    // update the text-content of the <style> element
    // using a template literal (delimited by backticks),
    // in which newlines don't require escaping and in which
    // JavaScript variables can be interpolated:
    style.textContent = `
      body { background-color: #f908; }
      ${importantElements} {color: ${importantColor};}`;

    // appending the created <style> element to the <head>:
    head.appendChild(style);
})();

References:

Bibliography:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • Thanks a lot for the detailed explanation. it was very nice It works! Also solution given by other folks worked as well. I noticed that i had to refresh the webpage in order to get it to work. I will search for some way to put the refresh code automatically in it. – Sach Dec 11 '18 at 10:31
  • 1
    In my own testing, so long as the script was enabled in Tampermonkey, no refresh was needed (and it doesn’t make sense that a refresh would be needed, given that it’s the same code being loaded). But you’re more than welcome to any help I was able to offer. – David Thomas Dec 11 '18 at 10:49
  • Yes that is strange, but i guess i will park it for a later investigation , atleast i got it working :) – Sach Dec 11 '18 at 14:08
2

You can achieve this by targetting all links that have a href which starts with your URL minus the query string, and then changing the href attribute of it to the new link.

Here I use:

a[href^="${old_link}"]

To get all anchor tags (a) which start with the value of old_link. This allows you to ignore the

?tNumber=*

At the end of your link.

See working example below:

let old_link = "https://www.google.com";
let new_link = "https://www.example.com/queries";
let links = document.querySelectorAll(`a[href^="${old_link}"]`);
[...links].forEach(link => link.href = new_link + '?' + link.href.split('?')[1]);
/* This is not needed, but used to demonstrate that the links have changed */

a[href^="https://www.example.com"] {
  color: red;
}
<a href="https://stackoverflow.com">This link doesn't change</a>
<br />
<a href="https://www.google.com?q=1">This link does change</a>
<br />
<a href="https://www.google.com?q=2&oq=200">This link does change</a>

Notice how the original links link to google.com?q=* but the links in the webpage actually link to *example.com?q=**.

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • Nick , appreciate the great detailed answer. I copied the 6 lines(after replacing with correct links) of code and put in new script section of tamper monkey . Still doesnt work . Was your answer just explanation code and that i will have to do some work on it to arrive at complete solution. Conceptually i have understood your answer , but i havent yet reached to putting working code with it – Sach Dec 08 '18 at 10:58
  • @Sach the code should work as is... Did you change the `old_link` and `new_link` variables to your desired links (without the `?` attached at the end) ? – Nick Parsons Dec 08 '18 at 11:00
  • Which ? are you referring to . i used this code window.onload = function() { let old_link = "https://oldwebe.company.com/xyz/Ticketnumber.jspx?tNumber="; let new_link = "https://companysachinperf.com/newweb/TicketDetnumber.jspx?tNumber=" let links = document.querySelectorAll(`a[href^="${old_link}"]`); [...links].forEach(link => link.href = new_link +'?'+ link.href.split('?')[1]); } – Sach Dec 08 '18 at 11:06
  • try: `let old_link = "oldwebe.company.com/xyz/Ticketnumber.jspx"; let new_link = "companysachinperf.com/newweb/TicketDetnumber.jspx";` instead (so removing everything after the `?`) – Nick Parsons Dec 08 '18 at 11:08
  • tried, still doesnt work. in fact tamper monkey usually shows up on top if script was run . And i do not see it running. How to verify if this was run indeed – Sach Dec 08 '18 at 11:21
  • @Sach What do you have set as your `@match` argument? – Nick Parsons Dec 08 '18 at 11:27
  • Are you running the site you're trying to change the links on locally or on a server? – Nick Parsons Dec 08 '18 at 11:37
  • also, try removing the `window.onload = function`. See my updated javascript. (So only include the four lines in the `(function() {//Enter 4 lines here})();`) – Nick Parsons Dec 08 '18 at 11:43
  • i am running locally, through tamper monkey as a javascript. trying without thefunction – Sach Dec 08 '18 at 12:20
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/184916/discussion-between-nick-parsons-and-sach). – Nick Parsons Dec 08 '18 at 12:21
  • 1
    As discussed below part is working sometimes unexpectedly and when restarting browser after deleting history it stops working. And there is no set way to trigger it , i will open a question for this incosistent behaviour in TamperMonkey let old_link = "companysachinperf.com/newweb/TicketDetnumber.jspx?tNumber="; let new_link = "oldwebe.company.com/xyz/Ticketnumber.jspx?tnumber"; let links = document.querySelectorAll(`a[href^="${old_link}"]`); [...links].forEach(link => link.href = new_link +'='+ link.href.split('=')[1]); – Sach Dec 08 '18 at 14:14
  • the solution is not working at all now and not inconsistent :(. I thought of testing it differently to get the right trigger to work. Not sure how to debug it. – Sach Dec 09 '18 at 11:17
  • Yes it worked, the trick i use is to refresh the webpage , the first time when i search for issue which brings up the ticket numbers – Sach Dec 11 '18 at 14:06
  • 1
    Great!! Awesome :) – Nick Parsons Dec 11 '18 at 14:07
1

You can change the href attribute of links like this:

function new2old(new_address) {
  let old_address = "https://oldwebe.company.com/xyz/Ticketnumber.jspx";
  let t = "";
  t = new_address.substring(new_address.lastIndexOf('?'), new_address.length);
  return old_address + t;
}

let links = document.querySelectorAll("a");

for (const link of links) {
  link.href = new2old(link.href);
}

Just put that in the <script> </script> at the end of your body section, just before the </body> tag (or run it in a console).

Kresimir
  • 777
  • 5
  • 20
1

Your attempted code will need minor correction at line where you are generating id, use "=" instead of "/"

var id = hrefVal.substr(hrefVal.lastIndexOf('=') + 1);
Mukund
  • 393
  • 2
  • 7
  • in next line( "console.log(newLink);") you are printing on console. so just press F12 on chrome browser go to console tab and check the output. on line( window.open(newLink,'_blank');) this open the new link on new window. So check if popup blockers are deactivated in browser. – Mukund Dec 08 '18 at 10:46
  • Mukund i use firefox and pop-up blocker was checked, i unchecked , still problem persists – Sach Dec 08 '18 at 10:54
  • firefox will also show developer tool on F12. check the new url that is getting generated.. Also check if any js errors on console when you click the link – Mukund Dec 08 '18 at 10:59
  • there are few errors and warnings but open and new links open without problem on their own. Also i do not see my javascript listed there. – Sach Dec 08 '18 at 11:23
  • check if you have added your changes at right place. Alternately, run your code on console and check the output by clicking link. – Mukund Dec 08 '18 at 11:30