Метод выбора элементов в Sizzle с использованием полных URL - PullRequest
4 голосов
/ 10 февраля 2012

Недавно работая над сценарием, я обнаружил странный нюанс , как Sizzle работает с атрибутом href .В частности, используя селектор атрибута на href, Sizzle будет использовать фактическое значение атрибута:

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

Sizzle использует .getAttribute() вместо elem.href (или, точнее, elem['href'], как в большинстве случаев Sizzle );elem.href предоставит полный URL-адрес.

Чтобы понять это немного подробнее, я создал скрипку, чтобы попробовал различные формы URL-адресов .В процессе тестирования я обнаружил (очевидное) «решение» , установив href равное себе :

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

, что неудивительно, что элемент обновляется, чтобы отразитьполный URL, предоставленный this.href.Есть и другие способы, которые я нашел для этой работы (любой, который обновляет атрибут href элемента), но они просто переносят вышеуказанный подход на другие формы или включают что-то вроде .filter() (демо) :

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

Причина, по которой я это говорю, заключается в том, что выполнение el.href = el.href перед выбором является в некотором смысле обходным решением (и я не думаю, что это отличная альтернатива).Например, выполнить проверку набора элементов, чтобы определить, содержат ли они соответствующую ссылку на текущий URL (или другой URL), проще, если вы можете:

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

Есть ли способсделать это, не прибегая к «обновлению» атрибутов или написанию дополнительного кода для управления проверкой?Есть ли способ, который я упустил из виду, который не включает изменение работы Sizzle ^ ?

^ Примечание : изменение фактического исходного кода было бы (плохо) идея по сравнению с простым добавлением 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/

(И, кроме того, есть ли другие атрибуты с похожим нетипичным поведением в Sizzle?)

1 Ответ

3 голосов
/ 07 марта 2012

Мне кажется, у меня есть ответ на этот вопрос ...

Используйте 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/

Или, как было отмечено в комментариях, можно использовать $.filter():

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

http://jsfiddle.net/dMuyj/

И этот jQuery возвращается к Sizzle, если querySelector() и querySelectorAll() не доступны изначально, и что оба они работают так же, как механизм выбора jQuery (не удивительно).

Общая сумма равнавам нужно либо выражение, либо фильтр, если вы хотите использовать этот тип селектора, и для сравнения используйте elem.href, а не getAttribute().

...