My goal is to detect an href click and do something if the link is an external link. I have the following JavaScript in place to detect external links:
var isThisDomain = href.match(document.domain.split('.').reverse()[1] + '.' + document.domain.split('.').reverse()[0]);
I then use the following to do something if an external link is detected:
else if (href != isThisDomain) {
// do something for external links
}
This works for external links but also fires for internal links with a #. For example, if my site is www.example.com I DO NOT want this to fire if href is www.example.com/#anchor or www.example.com/category/#anotheranchor.
How do I change isThisDomain to cater for this hash?
Have you tried using document.location.hostname (which only gets the host name part of the URL and excludes everything else) and comparing it to the URL you have?
If you're doing this to every link on the page, you'll need to set an EventListener on all links that check the host property on them. If it's external, do whatever you need to. It looks like this:
function checkHref(e) {
var url = e.target.href,
externalUrl = e.target.host !== document.location.hostname;
if (externalUrl) {
console.log(e); // Place your logic here.
}
e.preventDefault();
}
var links = document.getElementsByTagName('a'),
i;
// Loop through all anchor elements and add an EventListener
for (i = 0; i < links.length; i++) {
var el = links[i];
el.addEventListener('click', checkHref, false);
}
Related
Here's my current code:
window.onload = function() {
document.querySelectorAll('a').forEach((anchor) => {
const href = anchor.getAttribute('href');
/:\/\//.test(href) && anchor.setAttribute('href', 'http://example.com/go=' + href);
console.log(anchor.getAttribute('href'));
});
}
The code is supposed to add http://example.com/go= before all external links.
If I link to an external page, it is adding it correctly. However, it's also adding it to internal pages depending on how I link to them. If I link to them like <a href="/testing"> it doesn't added it (which is correct.
But if I link to my website like <a href="http://website.com/testing"> then it's assuming that's an external URL since I included the domain and adding the string before it.
What am I doing wrong?
You can replace the regular expression you use to test with one that also checks that the href domain does not bein with website.com: change
/:\/\//
to
/:\/\/(?!website\.com)/
You also might consider using an if statement instead of &&, to make the code more readable (leave the tricky-looking &&-as-if to the minifiers):
document.querySelectorAll('a').forEach((anchor) => {
const href = anchor.getAttribute('href');
if (/:\/\/(?!website\.com)/.test(href)) {
anchor.setAttribute('href', 'http://example.com/go=' + href);
}
console.log(anchor.getAttribute('href'));
});
Also note that querySelectorAll returns a NodeList, not an array, and only newer browsers support NodeList.prototype.forEach - Chrome users on Vista and older systems will run into errors, for example, so if you want to support them, make sure to include a polyfill, if you aren't already.
If you have to, you can dynamically create the regular expression from the current domain by checking window.location.hostname:
document.querySelectorAll('a').forEach((anchor) => {
const { hostname } = window.location;
const escapedHostname = hostname.replace(/\./g, '\\.');
const pattern = new RegExp(`://(?!${escapedHostname})`);
const href = anchor.getAttribute('href');
if (pattern.test(href)) {
anchor.setAttribute('href', 'http://example.com/go=' + href);
}
console.log(anchor.getAttribute('href'));
});
I am using MVC webgrid and an artifact of navigating the page is I have lots of urls that look like like:
►
I need to change entrystate=Templates to entrystate=Paging.
Is there a jscript way to make this change for all the links in a simple script ?
The links are being generated by the webgrid component and I have no access to it. They seem to be formed because the grid takes the url that invokes the action and uses it as a base url (entrystate and modelIn are routevalues invoking the action). I have no control over this. My only option seems to be fixing the html after it is created. I am stuck with this lame grid.
Try this:
$('a[href~="/SyntheticData/MasterDetail?"]').each(function() {
$(this).attr('href', $(this).attr('href').replace('entrystate=Templates', 'entrystate=Paging'));
});
I used a wildcard selector to partially match the href so it doesn't loop through links that are unrelated. You may need to adjust it.
oops, you aint using jquery perhaps?
I was hoping for something simplter but this looks like it will work:
var links = $("a[href]");
for (var i = 0; i < links.length; i++) {
var link = links[i];
var urlin = link.attributes.getNamedItem("href");
var urlout = urlin.value.replace("entrystate=Templates", "entrystate=Paging");
var urlout2 = urlout.replace("entrystate=Designer", "entrystate=Paging");
link.setAttribute("href", urlout2);
}
I ended up using (thx suncat100):
$('a[href*="entrystate="]').each(function () {
var url = $(this)[0].attributes.getNamedItem("href").value;
url = url.replace("entrystate=Templates", "entrystate=Paging");
url = url.replace("entrystate=Designer", "entrystate=Paging");
$(this)[0].setAttribute("href", url);
});
});
I am loading all website's pages into the main index page, and updating URL display by splitting the href into segments and adding the segments after the main domain name with .hash function, like this:
$('a').click(function(event) {
event.preventDefault();
var my_url = this.href;
var pathArray = this.href.split('/');
var newPathname = "";
for ( i = 3; i < pathArray.length; i++ ) {
newPathname += "/";
newPathname += pathArray[i];
}
$('body').load(my_url);
window.location.hash = newPathname;
This works okay, but I'm facing a little problem. When a user accesses http://www.mywebsite.com/ and then clicks, for example, on "About" link, the selected page loads, and the address bar displays:
http://www.mywebsite.com/#/about
But if a user starts with a different page:
http://www.mywebsite.com/#/about
Then after the click, the url becomes:
http://www.mywebsite.com/#/about/#/about
and so on, to infinity.
How can this be solved?
Perhaps there's a way to clear the hash and then display the new hash (that is, remove everything that starts with #/ and then add the new hash) – or maybe there's a better solution?
Try var my_url = this.href.replace(/#.*/,'')
This will remove the # and anything after it.
If you want to split just the path component of the current URL, then don’t use
var pathArray = this.href.split('/');
because href will contain the full path including the hash.
Use
var pathArray = this.pathname.split('/');
instead.
Changing the hash doesn't refresh your page. At most it forces the browser to scroll top. If you want you can do:
window.location.hash = "";
to empty it (retaining the #) if you also remove the #from the href then your page will always reload.
I'm creating a bilingual website for a client. Two versions of the site in different languages will be created and stored in two folders:
/en/
/chi/
What I want to do is create a link to toggle between the two languages. On the conceptual level, I understand that Javascript can detect the current URL and split it into its different components, modify parts of it (in this case change between /en/ and /chi/), and then go to that new URL when the link is clicked.
But I have zero knowledge in javascript so I have no idea how to execute... I have come across this page:
http://css-tricks.com/snippets/javascript/get-url-and-url-parts-in-javascript/
but it doesn't explain how to modify and go to the new link.
You help will be greatly appreciated!!
To not break usability considerations like Shift + Click to open in a new window, you should create a plain old link (<a>) that points to the other language URL. There's nothing wrong with building the link via JavaScript, but you could also do it on the server using PHP or whatever templating language you're using.
Here's a script that does this with JavaScript if that's what you decide you'd like to do.
<!DOCTYPE html>
<body>
Content before the link.
<script>
(function () {
// this assumes you're on the en version and want to switch to chi
var holder = document.createElement("div");
var url = window.location.href.replace("/en/", "/chi/");
var link = document.createElement("a");
link.innerText = "Chewa"; // or whatever the link should be
link.href = url;
holder.appendChild(link);
document.write(holder.innerHTML);
})();
</script>
Content after the link.
</body>
If you simply want to take the full URL and replace /en/ with /chi/ or vise-versa, use the code below.
HTML
<span onclick="SwitchLang()">View [Some other Language]</span>
JavaScript
function SwitchLang() {
//Does URL contain "/en/"?
if(window.location.href.indexOf("/en/") != -1) {
//URL contain "/en/", replace with "/chi/"
window.location.href = window.location.href.replace("/en/", "/chi/");
}
//Does URL contain "/chi/"?
else if(window.location.href.indexOf("/chi/") != -1) {
//URL contain "/chi/", replace with "/en/"
window.location.href = window.location.href.replace("/chi/", "/en/");
}
}
Or, a bit more concise (un-commented version)
function SwitchLang() {
if(window.location.href.indexOf("/en/") != -1)
window.location.href = window.location.href.replace("/en/", "/chi/");
else if(window.location.href.indexOf("/chi/") != -1)
window.location.href = window.location.href.replace("/chi/", "/en/");
}
Note: In JS, when you modify window.location.href, the new URL is automatically loaded.
Here's a working fiddle for you to play with.
It looks like you need to change the window.location.pathname. For example:
// assuming the url `http://www.example.org/en/foo/bar/page.html`
var paths = window.location.pathname.split("/");
// change `en`
paths[1] = "chi";
// go to the new url
window.location.pathname = paths.join("/");
See:
https://developer.mozilla.org/en/DOM/window.location
I have a simple link inside my tml (apache tapestry specific) :
www.google.com
Now on the browser if I am trying to click the link, actually it's redirecting to
http://localhost:8080/..../..../www.google.com
Instead of it should open a new tab for that link.
So the logic which I am thinking is :
1) Fire a javascript on page load
2) Get the href value of anchor tag
3) Append http:// at the start, if it doesn't contains it.
So to do this, actually I want to use prototype (javascript framework), and I am bit new to this...
How can I write the function using the Prototype.js library?
You don't say where the value for your href is coming from. As you say you need to prepend an "http". Assuming the link is dynamically rendered, why don't you just do this server-side, probably much easier. In tml:
... href="${url}" ....
and in .java:
public String getUrl() {
return "http://" + url;
}
This is a much better approach than doing it client-side as what happens if the user has javascript turned off?
On the other hand, if it's a static link in your .tml, just write "http://www.google.com"!
Edit: In light of your comment below:
public String getUrl() {
if (!url.startsWith("http://") {
url = "http://" + url;
}
return url;
}
The above is just an example of what do do. You can either add another method to activityDetails which does this (e.g getExternalLinkWithProtocol()), or provide a wrapper method similar to the one above.
No reason to do this on the client side. Simply change your template to:
www.google.com
and if it's based on a property:
${hostname}
... adjust to fit your properties, etc.
window.onload = function(){
var links = document.links;
for(var i=links.length-1; i>=0; i--){
var link = links[i];
var href = link.getAttribute("href");
if(href.indexOf("http://") < 0){
link.href = "http://" + href;
}
}
};