2

Sorry in advance - there are SO many variances of this question on SO, but none have resolved my issue. I have read so many variations that I am now completely confused on how to do this.

I have this Javascript function that appends UTM params to all offsite links except those with specific classes as such:

// Set the domain/URL of website.

var myDomain = "domain.com";

// Grab all links (anchor tags)
var links = document.querySelectorAll('a:not(.this-class)');

// Loop through all links
Array.prototype.forEach.call(links, function (link) {

// If a link goes offsite (not to my myDomain above)
if ( link.href.indexOf(myDomain) < 0 ) {

// Take the href and append the UTM parameters
link.href += '?utm_source=CampaignSource&utm_medium=CampaignMedium&utm_term=CampaignTerm&utm_content=CampaignContent&utm_campaign=CampaignName';
    }   
})

Now, I need to prevent appending to

ul.another_class li a

I have tried a myriad of syntaxes and formats, but just can't get it to work correctly. Such as

var links = document.querySelectorAll('a:not(.this-class),ul:not(.another_class li a)');

and way too many more to list here. The selector ul.another_class li a, only the ul has a class - neither the li nor the a does.

So, my question is both about the correct :not selector syntax AND the proper statement syntax. It is supposed to be

('a:not(.this-class), ul:not(.another_class li a)');

or

('a:not(.this-class), ul.another_class:not(li a)');

or something else? I appreciate your expertise.

KillerDesigner
  • 485
  • 1
  • 6
  • 18
  • You could always iterate the `ul.another_class li a` elements first and add `this-class` to them. – Phil Mar 30 '20 at 22:56
  • Thanks Phil. Given the codeblock above, how so? – KillerDesigner Mar 30 '20 at 23:16
  • 1
    `document.querySelectorAll('ul.another_class li a').forEach(a => a.classList.add('this-class'))` then you can just use your code as above – Phil Mar 30 '20 at 23:18
  • Thanks Phil! That DID work! The obvious caveat is the application of .this-class styles being applied. If I can't figure out CertainPerformances solution below, I'll use this. Appreciate you! – KillerDesigner Mar 30 '20 at 23:37

1 Answers1

2

It's not possible concisely with a single selector, because there is no parent selector. I think the best thing to do here would be to filter out the ul.another_class li a afterwards:

for (const a of document.querySelectorAll('a:not(.this-class)')) {
  if (!a.matches('ul.another_class li a')) {
    // manipulate the href
  }
}
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Sorry, the original post DID include the entire function. So, would I simply move the Array.prototype.forEach inside the for statement at **// manipulate the href**? – KillerDesigner Mar 30 '20 at 23:10
  • No, the `a` in the `for` block above is the `a` whose `href` you want to manipulate - just examine its `href` and do stuff to it, eg `a.href` – CertainPerformance Mar 30 '20 at 23:11
  • Oh, right, however, I want to exclude that selector from manipulation. So, for all offsite links *except* **a.this-class** and **ul.another_class li a**. Still valid? – KillerDesigner Mar 30 '20 at 23:15
  • 1
    That's what the logic there does - `a:not(.this-class)` selects `a`s which are not `.this-class`, and the `matches` test makes sure that, of those, only those which don't match `ul.another_class li a` get manipulated – CertainPerformance Mar 30 '20 at 23:17
  • Not sure if you saw Phil's solution above, which worked. Thanks for clarifying the logic, that makes sense now. I'm just not sure how to go about manipulating the href in context of the previous solution. Do I remove that function and append the UTM? If so, how so? – KillerDesigner Mar 30 '20 at 23:39
  • You just put whatever logic you need to apply to those `a`s inside the `if` block, eg `if (!a.href.includes(myDomain)) a.href += '...'` – CertainPerformance Mar 31 '20 at 00:10