Built relative URL in pages that are missing trailing slash / - javascript

We desperately need help with writing a small code that allows you to take the current page URL and the parameter in the href="parm" and create the link by joining the two with a slash.
The reason we need to do this is because we need relative links to the current page. The CMS system that we are working removes trailing slash from the end of URL.
Which is a problem because if you are at a page
domain.com/fruit/apple
and create a link such as href="calories" or href="./calories"
it will point to domain.com/fruit/calories
Instead, we want it to point to
domain.com/fruit/apple/calories
Which is relative to the current page.
We don't want to change the way that our CMS works, therefore, the need JS solution.
Below you can see one example of what we are trying to accomplish but this only works on one link.
link
Start JS
var x = window.location.href; // Current page URL
var link = document.getElementById("relurl"); // store the element
var curHref = link.getAttribute('href'); // Get HREF paramter
link.setAttribute('href', x + "/"+ curHref);
End JS
The idea is to build relative links every time links with id="relurl" is used.
As per previous example this link: a href="home" id="relurl" target="_blank" title="This is a relative link!">link
at this page: domain.com/fruit/apple
it should point to domain.com/fruit/apple/home
Meaning the link structure is the currentpageURL + / + href
One page may have multiple relative links.
Thanks for any help.

While you could just use relative URLs in your links (with href="./page"), it sounds like the problem is that you are using duplicate IDs (which results in invalid markup). You can test that you have valid markup with the W3C Markup Validation Service.
When you have duplicate IDs, JavaScript only applies to the first element. This can be seen in the following:
var x = window.location.href; // Current page URL
var link = document.getElementById("relurl"); // store the element
var curHref = link.getAttribute('href'); // Get HREF paramter
link.setAttribute('href', x + "/" + curHref);
Working Link
<br />
NOT Working
To resolve this, you should use classes instead of IDs for your links. You can then use document.getElementsByClassName to select the elements. Remember that this returns a NodeList collection of elements, so you'll need to set the new URLs inside of a loop, as can be seen in the following:
var x = window.location.href; // Current page URL
var links = document.getElementsByClassName("relurl"); // store the elements
for (var i = 0; i < links.length; i++) {
var curHref = links[i].getAttribute('href'); // Get HREF paramter
links[i].setAttribute('href', x + "/" + curHref);
}
Working Link
<br />
Another Working Link
Hope this helps! :)

This will update all links in the current page:
const updateNode = node =>
node.href = `${window.location}/${node.href}`
document.querySelectorAll('a').forEach(updateNode)

Related

How to link to the current URL + 1 using JavaScript?

I'm looking to create a simple nav link that goes to the next or previous page in a series. The URL ends in a number and each successive page is just the next number in the sequence (.../101, /102, /103, etc). Is there a way to use javascript to link to the current URL + or - 1?
I know basically no javascript besides what I can copy and paste into HTML.
How do I solve this problem?
You need to take location.href, take pathname, split it and increment the last item with the value. Then join and assign to the pathname. Finally append the element to the body (or any other location).
Further readings:
Location all about <a>
document.location where you get the actuall href
var url = document.createElement('a'),
pathes;
url.href = 'http://example.com/123'; // or at the site: location.href
url.appendChild(document.createTextNode('link'));
pathes = url.pathname.split('/');
pathes[pathes.length - 1] = +pathes[pathes.length - 1] + 1;
url.pathname = pathes.join('/');
document.body.appendChild(url);

Button/link to redirect up or down a level

I have two different levels within my site, but each have a similar structure. For example:
http://example.com/demo/insights.html
and
http://example.com/demo/complete/insights.html
What I'd like to do is add a link/button that the user can click to go up or down a level depending on where they are. The last part of the URL (e.g., insights.html) would stay the same. It's just whether or not the directory would change up or down.
So, if I'm on http://example.com/demo/insights.html, there would be a button to get to http://example.com/demo/complete/insights.html. If I was on http://example.com/demo/complete/insights.html
then there'd be a button to get to http://example.com/demo/insights.html.
I have a lot of pages like this, but I'd like to avoid hand-coding links on every page. I'm looking for something using javascript/jquery that will evaluate the directory level and the last part of the URL and redirect accordingly.
Any insights would be appreciated.
window.location.href
will give you the url of the page you are on, from there its just a matter of splitting split() the location and add/remove the required url substring
you can then add the new url into a common 'a' tag's href property on the page
As a rough example
var loc = window.location.href,
someSplits = loc.split("http://example.com/demo/"),
//you can do better reg ex, this is just quick
page = someSplits[1]; // this will give you the remaining url
// OR just replace the part you dont want
var loc = window.location.href,
page = loc.replace('http://example.com/demo/', '');
// this will give you the remaining url
One way to do this is to count slashes:
var link = window.location.href;
var deep = link.match(/\//g).length - 3;
var chunks = link.split(/\//);
if (deep) { // level 2
link = chunks[0] + '//' + chunks[2] + '/' + chunks[4]; // get rid of one level (chunks[3])
} else { // level 1
link = chunks[0] + '//' + chunks[2] + '/extra-level/' + chunks[3]; // add a level
}
You can use this:
location.assign('../'+location.pathname.substring(location.pathname.lastIndexOf("/") + 1))

Change the pathname in the URL of a link while keeping the querystring constant

From a page with the following URL, http://example.com/foo.html?query=1&other=2, I want to create a link to http://example.com/bar.html?query=1&other=2. How do I do that without explicitly saving and reloading all the query strings.
I need this to easily link from an iframe version of a page (embed.html?query) to the full page (index.html?query).
I would have recommended using the Location object's search method (available at document.location or window.location) to pull out the parameters, then modify the rest of the URL, but that API is apparently specific to Firefox.
I would simplify #DMortensen's answer by just splitting on the first ?, then modifying the first part (which will be the URL's path portion only), and reapplying the second part.
If you need to parse the parameters, I recommend the jQuery plugin Query Parameter Parser: one call to $.parseQuery(s) will pull out an object of all the keys & values.
It can be finicky, but you could split the URI on '?' and then loop through the 2nd element of that array to grab the key/val pairs if you need to evaluate each pair (using '&' as a delimiter). The obvious weakness in this would be if there are additional '?' or '&' used in the URI.
Something like this maybe? (pseudocode-ish)
var URI = document.URL;
var qs = URI.split('?');
var keyvalpair = qs[1].split('&');
var reconstructedURI = '&' + keyvalpair;
for(var i = 0; i< keyvalpair.length; i++){
var key = keyvalpair[i].split('=')[0];
var val = keyvalpair[i].split('=')[1];
}
Thank you for all the answers. I tried the following and it works.
function gotoFullSite() {
var search = window.location.search;
window.open("http://example.com/"+search)
}
$('#clickable').click(gotoFullSite);
and then use <a id = "clickable" href="#"></a>. When I click the link, it opens the proper website with all the query parameters in a new tab. (I need a new tab to break out of an iframe.)

Add body #id based on url

Need help! I've been looking for a solution for this seemingly simple task but can't find an exact one. Anyway, I'm trying to add custom #id to the tag based on the page's URL. The script I'm using works ok when the URLs are like these below.
- http://localhost.com/index.html
- http://localhost.com/page1.html
- http://localhost.com/page2.html
-> on this level, <body> gets ids like #index, #page1, #page2, etc...
My question is, how can I make the body #id still as #page1 or #page2 even when viewing subpages like this?
- http://localhost.com/page1/subpage1
- http://localhost.com/page2/subpage2
Here's the JS code I'm using (found online)
$(document).ready(function() {
var pathname = window.location.pathname;
var getLast = pathname.match(/.*\/(.*)$/)[1];
var truePath = getLast.replace(".html","");
if(truePath === "") {
$("body").attr("id","index");
}
else {
$("body").attr("id",truePath);
}
});
Thanks in advance!
edit: Thanks for all the replies! Basically I just want to put custom background images on every pages based on their body#id. >> js noob here.
http://localhost.com/page2/subpage2 - > my only problem is how to make the id as #page2 and not #subpage2 on this link.
Using the javascript split function might be of help here. For example (untested, but the general idea):
var url = window.location.href.replace(/http[s]?:\/\//, '').replace('.html', '');
var segments = url.split('/');
$('body').id = segments[0];
Also, you might want to consider using classes instead of ID's. This way you could assign every segment as a class...
var url = window.location.href.replace(/http[s]?:\/\//, '').replace('.html', '');
var segments = url.split('/');
for (var i = 0; i < segments.length; i++) {
$('body').addClass(segments[i]);
}
EDIT:
Glad it worked. Couple of notes if you're planning on using this for-real: If you ever have an extension besides .html that will get picked up in the class name. You can account for this by changing that replace to a regex...
var url = window.location.href.replace(/http[s]?:\/\//, '');
// Trim extension
url = url.replace(/\.(htm[l]?|asp[x]?|php|jsp)$/,'');
If there will ever be querystrings on the URL you'll want to filter those out too (this is the one regex I'm not 100% on)...
url = url.replace(/\?.+$/,'');
Also, it's a bit inefficient to have the $('body') in every for loop "around" as this causes jQuery to have to re-find the body tag. A more performant way to do this, especially if the sub folders end up 2 or 3 deep would be to find it once, then "cache" it to a variable like so..
var $body = $('body');
for ( ... ) {
$body.addClass( ...
}
Your regex is only going to select the last part of the url.
var getLast = pathname.match(/./(.)$/)[1];
You're matching anything (.*), followed by a slash, followed by anything (this time, capturing this value) and then pulling out the first match, which is the only match.
If you really want to do this (and I have my doubts, this seems like a bad idea) then you could just use window.location.pathname, since that already has the fullpath in there.
edit: You really shouldn't need to do this because the URL for the page is already a unique identifier. I can't really think of any situation where you'd need to have a unique id attribute for the body element on a page. Anytime where you're dealing with that content (either from client side javascript, or from a scraper) you should already have a unique identifier - the URL.
What are you actually trying to do?
Try the following. Basically, it sets the id to whatever folder or filename appears after the domain, but won't include a file extension.
$(document).ready(function() {
$("body").attr("id",window.location.pathname.split("/")[1].split(".")[0]);
}
You want to get the first part of the path instead of the last:
var getFirst = pathname.match(/^\/([^\/]*)/)[1];
If your pages all have a common name as in your example ("page"), you could modify your script including changing your match pattern to include that part:
var getLast = pathname.match(/\/(page\d+)\//)[1];
The above would match "page" followed by a number of digits (omitting the 'html' ending too).

function to define current class in js

What I want to do is to have a function that executes to define a "current" class to an <li> tag, depending on the page name. For example, if the page is named index.php, I want the function to determine if the link within the <li> tag is the same name as the page (index.php). I'm sorry I'm not the best at explaining this. Here's an example code.
<ul id="navigation"><li><a href="index.php"></li></ul>.
I want the class "current" defined into the <li> tag if the link is the same as the page name. Is there any way to do this? Or am I on a futile mission?
I think what you are asking is you want to change the look of links that are pointing to the present page. Here is what the code would look like.
var list=document.getElementsByTagName('a');
var page=window.location.pathname;
var i=list.length;
while(i--){
if(list[i].src.indexOf(page)>0){
list[i].className='current';
}
}
Note this is not a very accurate method. The basic structure is correct, but for example a link somewebsite.com is actually pointing to somewebsite.com/index.php. So depending on the link this could cause a problem on the home page. Also, depending on how your links are setup you are probably going to have to the parse the page variable. It will return something like. /help/faq/foo.php while the page may only have a link to faq/foo.php. This all depends a lot on the setup of your site so I will leave it for you to tweak.
You added more details since I posted so I thought I would note that you would only need to make a list of the links in the <li> tags not all the <a> tags in the page.
Well...okay...
function liClass(context) {
//Choose your parent node
context = context || document;
var pathparts = window.location.pathname.split('/'); //split on path
var curfile = pathparts[pathparts.length-1]; //last item is the filename right?
var lis = context.getElementsByTagName('li');
for (var i=0, l=lis.length; i<l; i++) {
var a = lis[i].getElementsByTagName('a');
if (!a.length) continue; //li has no a, moving on...
//Okay, this match might need some work, tried
//to make it fairly forgiving, tweak for your needs
if (a[0].href.indexOf(curfile) != -1) lis[i].className = 'current';
}
}
Feel free to try it out, let me know if it works or not, cause I did not test it...
Compare the href's of the location object, and the anchor DOM element. If they match, then that is the current class.
If the current page is http://www.example.com/home which contains a relative link,
Questions
Then the href property of the DOM object will contain the absolute path, and not just the relative part.
link.href = "http://www.example.com/questions"
A function that loops through each link could then be written as,
function markCurrent(list) {
var listItems = list.getElementsByTagName("li");
for(var i = 0; i < items.length; i++) {
var link = listItems[i].getElementsByTagName("a")[0];
if(link && (link.href == location.href)) {
listItems[i].className += ' current';
}
}
}
Pass the root <ul> node to the function.
markCurrent(document.getElementById("navigation"));

Categories