jQuery替换相对链接

时间:2012-03-01 17:11:22

标签: javascript jquery

希望有人可以解释我在jQuery中遇到的一些奇怪的行为。以下脚本正在我的页面上查找相关链接并用绝对链接替换它们。

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

我在将通过https提供的页面上使用此脚本,但我不希望所有导航都链接到https页面。由于我的导航是全局包含的,这似乎是解决问题的最简单方法。

我遇到的问题出现在实际更换中。脚本的第二行正确匹配页面上的所有相对链接,然后运行脚本的替换部分。这是替换,第4行,我得到一些奇怪的结果。在这部分脚本运行后,我的URL最终看起来像这样:

  

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

显然没有做我想做的事。看起来脚本的第一部分与相对URL匹配,但当替换部件触发时,浏览器已经添加了域信息。

到目前为止,我发现的唯一能够实现我想要的就是编写替代品,预测浏览器的内容:

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

有更好的方法吗?


修改:here is a jsfiddle of the problem

6 个答案:

答案 0 :(得分:3)

jQuery在这里没有引起问题。问题是HTMLAnchorElement的href属性(jQuery返回的对象类型)per the spec始终包含绝对URI。

在HTML5中,hrefa composite attribute,您可以通过修改//来随意交换协议(href.protocol之前的部分),例如:

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

对于没有复合href的旧浏览器,您只需要使用正则表达式:

console.log( link.href );
// => https://example.com/foo

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

TLDR:您的代码应如下所示:

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

P.S。您会注意到我已经删除了$.each来电。这是因为prop会自动对匹配集中的每个元素执行操作,即它已经执行了您使用each执行的操作。


  

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

     
      
  • propertyName 要设置的媒体资源的名称。
  •   
  • function(index, oldPropertyValue) 将值设置为set的函数。接收set中元素的索引位置和旧属性值作为参数。在函数中,关键字this引用当前元素。
  •   

答案 1 :(得分:1)

代码:

$(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;
            });
        });
    });
});

请参阅此jsfiddle:http://jsfiddle.net/aknosis/kWrjr/

以下是我对此问题的解决方案的链接:http://aknosis.com/2011/07/17/using-jquery-to-rewrite-relative-urls-to-absolute-urls-revisited/

答案 2 :(得分:1)

这不是很好,但它应该适用于各种浏览器:

$(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);
    }  
  });
});

答案 3 :(得分:0)

尝试这样的事情:

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

}

答案 4 :(得分:0)

.prop()获取属性值,而不是属性值。虽然相似,但有一些微妙的,重要的差异 - 其中一个适用于此。元素上的href属性始终完整路径。例如:

<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>

换句话说,您将域附加到已经是绝对路径的值。只需使用.attr()而不是.prop(),您就可以了。

要查看示例,请打开控制台并转到此页面:http://jsfiddle.net/JUcHU/

答案 5 :(得分:0)

只需使用

即可
$(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);
  });
});