JQuery replaces relative links

Hope someone can explain some weird behavior I came across with jQuery. The following script searches for relative links on my page and replaces them with absolute links.

$(document).ready(function() { $("a[href^='/']").each(function(){ var cur_href = $(this).prop("href"); $(this).prop("href", 'http://www.mysite.com'+cur_href); }); }); 

I use this script on a page that will be transmitted over https, but I do not want all of my navigation to link to https pages. Since my navigation system was included globally, this seemed like the easiest way to fix the problem.

The problem that I am facing comes in a real replacement. The second line of the script matches all the relative links on the page correctly and then runs the replaceable part of the script. It is in replacement, line 4, where I get some strange results. After this part of running the script, my URLs look like this:

Http: //www.mysite.comhttps//www.mysite.com/mypage.htm

Obviously, I am not doing what I want. It seems that the first part of the script corresponds to the relative URL, but when the spare part fires, the browser is already tied to the domain information.

The only thing I have found so far that actually does what I want is to write a replacement, expecting the browser to overlay:

 this.href = this.href.replace(/^https:\/\/www\.mysite\.com\//, "http://www.mysite.com/"); 

Is there a better way to do this?


Edit: here is the jsfiddle problem .

+4
source share
6 answers

jQuery does not cause a problem here. The problem is that the href property for HTMLAnchorElement (return type of jQuery object), per specification , always contains an absolute URI.

In HTML5, href has a composite attribute , and you can simply change the protocol (part before // ) as desired by changing href.protocol , for example:

 var link = $( '<a href="https://example.com/foo">bar</a>' )[0]; console.log( link.href ); // => https://example.com/foo link.href.protocol = 'http:'; console.log( link.href ); // => http://example.com/foo 

For older browsers without composite href you just need to do this with a regex:

 console.log( link.href ); // => https://example.com/foo link.href = link.href.replace( /^https:/, 'http:' ); console.log( link.href ); // => http://example.com/foo 

TL; DR: Your code should look something like this:

 $( "a[href^='/']" ).prop( "href", function( _idx, oldHref ) { return oldHref.replace( /^https:/, 'http:' ); } ); 

PS You will notice that I rejected your call to $.each . This is because prop automatically acts on each element in a consistent set, i.e. Already does what you did with each .


. prop (propertyName, function (index, oldPropertyValue))

  • propertyName The name of the propertyName set.
  • function(index, oldPropertyValue) A function that returns the given value. Gets the index position of the element in the set and the value of the old property as arguments. Inside the function, the this refers to the current element.
+3
source

The code:

 $(function() { $('input').click(function() { $('a').not('[href^="http"],[href^="https"],[href^="mailto:"],[href^="#"]').each(function() { $(this).attr('href', function(index, value) { if (value.substr(0,1) !== "/") { value = window.location.pathname + value; } return "http://mynewurl.com" + value; }); }); }); }); 

See this jsfiddle: http://jsfiddle.net/aknosis/kWrjr/

Here is a link to my solution to this problem: http://aknosis.com/2011/07/17/using-jquery-to-rewrite-relative-urls-to-absolute-urls-revisited/

+1
source

This is not very, but it should work in different browsers:

 $(document).ready(function() { $("a[href^='/']").each(function(){ var cur_href = $(this).attr("href"); if( cur_href.indexOf( "http" ) !== -1 ) { $(this).attr("href", cur_href); } else { $(this).attr("href", 'http://www.mysite.com'+cur_href); } }); }); 
+1
source

Try something like this:

 if(! /http/.test( cur_href) ){ $(this).attr("href", 'http://www.mysite.com'+cur_href); } 
0
source

.prop() captures the value of a property as opposed to a value . While similar, there are some subtle, important differences - one of which is applicable here. The href property for an element is always the full path. For instance:

 <a id="myAnchor" href="/foo.html"></a> <script> elem = document.getElementById('myAnchor'); $elem = $(elem); alert(elem.href); //alerts the full path, http://www.example.com/foo.html alert($elem.prop('href')); //same as above alert($elem.attr('href')); //alerts just "/foo.html" </script> 

In other words, you add the domain to a value that is already an absolute path. Just use .attr() , not .prop() , and everything will be fine.

To see an example, open the console and go to this page: http://jsfiddle.net/JUcHU/

0
source

just try

 $(document).ready(function() { $("a[href^='/']").each(function(){ var cur_href = this.href; /* <-- access to the href attribute through the DOM reference */ $(this).prop("href", 'http://www.mysite.com'+cur_href); }); }); 
0
source

Source: https://habr.com/ru/post/1399230/


All Articles