Method for selecting elements in Sizzle using fully-qualified URLs

空扰寡人 提交于 2019-11-28 09:00:38

问题


While working on a script recently, I came across a peculiar nuance of how Sizzle works with the href attribute. Specifically, using an attribute selector on an href, Sizzle will use the actual attribute value:

// Will not find <a href="index.html">...
$('a[href="http://www.example.com/index.html"]')

Sizzle uses .getAttribute() instead of elem.href (or more precisely, elem['href'], as Sizzle does in most cases); elem.href would provide the fully-qualified URL.

To understand this a bit more, I created a fiddle to try different forms of URLs. In the process of testing, I discovered the (obvious) "solution" of setting the href equal to itself:

$('a').each(function(){
    this.href = this.href;
});

Which, unsurprisingly, updates the element to reflect the fully-qualified URL that this.href provides. There are other ways I've found that work (any that update the href attribute of an element), but they just port the above approach to other forms, or involve something like .filter() (demo):

var matches = $('a').filter(function(){
    var window_location = 'http://example.com/services.html';
    return window_location == this.href;
});

The reason I say this is that doing el.href = el.href before selecting is a workaround in a sense (and one I don't think is a great alternative). For instance, running a check on a set of elements to find if any contain a matching link to the current URL (or another URL) is simpler to do if you can:

$links.not('[href="' + window.location.href + '"]')

Is there a way to do this without having to resort to "updating" the attributes, or writing additional code to manage the check? Is there a way I've overlooked that doesn't involve modifying how Sizzle works ^?

^ Note: Modifying the actual source code would be a (bad) idea compared to just adding an expression:

$.extend($.expr[':'], {
    url: function(elem, i, match){
        return elem.href === match[3];
    }
});

var $matched = $('a:url(http://test.com/index.html)');

http://jsfiddle.net/yt2RU/

(And as an aside, are there other attributes with similar untypical behavior in Sizzle?)


回答1:


I believe I've got the answer to this question...

Use either an expression:

jQuery.extend(jQuery.expr[':'], {
    url: function(elem, i, match){
        return elem.href === match[3];
    }
});

var $matched = jQuery('a:url(http://test.com/index.html)');

http://jsfiddle.net/yt2RU/

Or, as it was noted in the comments, $.filter() could be used:

var $matched = $('a').filter(function(){
    if (this.href == 'http://test.com/index.html') {
        return true;
    }
    return false;
});

http://jsfiddle.net/dMuyj/

And that jQuery only falls back to Sizzle if querySelector() and querySelectorAll() are not available natively, and that both of these work the same as jQuery's selector engine (not surprising).

The sum total is, you either need an expression or a filter if you desire this type of selector, and use elem.href for the comparison, not getAttribute().



来源:https://stackoverflow.com/questions/9222026/method-for-selecting-elements-in-sizzle-using-fully-qualified-urls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!