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'));
});
Related
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);
}
I have a small tool build with Delphi that collects url's from a file or from the clipboard, and than builds a file called test.htm with a content like this :
<!DOCTYPE html>
<html>
<body>
<p>Click the button retrieve the links....</p>
<button onclick="myFunction()">Click me</button>
<p id="demo"></p>
<script>
function myFunction() {
window.open('http://www.speedtest.net/', '_blank');
window.open('www.speedtest.net/', '_blank');
and so on...
}
</script>
</body>
</html>
The idea is to click on the button, and then a new tab (or window) is created for every url inside myFunction.
This works, but with one small problem.
In the code example there are 2 url's, one with the http:// prefix and one without it. The first url works as expected and creates a new tab (or window) with the following url:
http://www.speedtest.net
The second 'window.open' does not work as I expected. This 'window.open' will create the following url in the new tab (or window)
file:///c:/myApplicaton/www.speedtest.net
As you have already figured out, the application is an executable in c:\myApplication
So my question(s) is, is there a way to use 'window.open' to create a new tab (or window) without putting the path of the application in front of the url ?
If this is not possible with 'window.open', is there another way to do this ?
Or is the only way to do this to have the application put the http:// in front of every url that does not have it already ?
As you suggested, the only way is to add the http protocol to each URL which is missing it. It's a pretty simple and straightforward solution with other benefits to it.
Consider this piece of code:
function windowOpen(url, name, specs) {
if (!url.match(/^https?:\/\//i)) {
url = 'http://' + url;
}
return window.open(url, name, specs);
}
What I usually do is to also add the functionality of passing specs as an object, which is much more manageable, in my opinion, than a string, even setting specs defaults if needed, and you can also automate the name creation and make the argument optional in case it's redundant to your cause.
Here's an example of how the next stage of this function may look like.
function windowOpen(url, name, specs) {
if (!url.match(/^https?:\/\//i)) {
url = 'http://' + url;
}
// name is optional
if (typeof name === 'object') {
specs = name;
name = null;
}
if (!name) {
name = 'window_' + Math.random();
}
if (typeof specs === 'object') {
for (var specs_keys = Object.keys(specs), i = 0, specs_array = [];
i < specs_keys.length; i++) {
specs_array.push(specs_keys[i] + '=' + specs[specs_keys[i]]);
}
specs = specs_array.join(',');
}
return window.open(url, name, specs);
}
I think the best way would be to add "//" + url
In this case - it isn't important, what protocol (http or https) you expect to receive as a result.
url = url.match(/^https?:/) ? url : '//' + url;
window.open(url, '_blank');
The only way to do this is to have the application put the http:// in front of every url that does not have it already.
For the behavior you're describing, you have to include your protocol with window.open. You could use a tertiary operator to simply include the protocol if it doesn't already exist:
url = url.match(/^http[s]?:\/\//) ? url : 'http://' + url;
Note that you'll need to use the SSL protocol sometimes, so this is not a complete solution.
I made small changes function form answered by iMoses which worked for me.
Check for both https OR http protocol
if (!url.match(/^http?:\/\//i) || !url.match(/^https?:\/\//i)) {
url = 'http://' + url;
}
Hope it make more accurate for other situation !
I am trying to get hostname from set of urls that my webapp can encounter with.
The desired output should be something like http://localhost/Webapp/, ending at /Webapp/ and everything after that should be removed.
Kindly note that I dont want to use word Webapp in regex as this name is dynamic and used for demo/testcase only.this can be anything , not harcoded.
In real example I am using location.href.replace(/index.+/g, "").replace(/#.+/g, "")
and I want to keep only hostname ending atWebapp/.
Problem:
my solution seems to working fine except "http://localhost/Webapp/#" is not working correctly ? why is that ? see fiddle below
JSFIDDLE: http://jsfiddle.net/bababalcksheep/um0uqb8v/
JS:
var getHost = function (url) {
return url.replace(/index.+/g, "").replace(/#.+/g, "")
};
var urls = [
"http://localhost/Webapp/",
"http://localhost/Webapp/#",
"http://localhost:8080/Webapp/#sdf#dfgdf#fdg",
"12.168.1.1:8080/Webapp/index.html#",
"https://localhost/Webapp/index.html#ab#bg",
"https://localhost/Webapp/index.html"
];
//Print all urls
$.each(urls, function () {
$("<p/>").text(getHost(this)).appendTo($(".test"));
});
Use url.match(/https?:\/\/([^\/]+)/);
EDIT:
It returns an array where the 1st element is the host with protocol and the 2nd without.
You can try removing anything after the last slash (files and hash-es):
var getHost = function (url) {
return url.replace(/\/[^/]*?$/, '/');
};
And here's the updated fiddle.
There's a bit of a trick you can use to get the browser to extract the hostname for you.
var getHost = function (url) {
var a = document.createElement('a');
a.href = url;
return a.hostname;
};
It also appears you want the path as well. You can access it with the pathname property of the a element. If you're doing that, you ought to rename the function to something like getHostAndPath().
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;
}
}
};