user3033194
user3033194

Reputation: 1831

Select subset of elements with jQuery

A part of an HTML page consisting of links is given below:

  <ul>
    <li><a href="myPersonalProject.html">myPersonalProject (a local html file)</a></li>
    <li><a href="cv.pdf">my CV (a local PDF file)</a></li>
    <li><a href="archive/2014.zip">archive (a local ZIP file)</a></li>
    <li><a href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf">ECMAScript Language Specification (an external PDF)</a></li>
    <li><a href="../pdfs/christmas/">Christmas cards (a local directory with pdf in the pathname - but NOT a pdf file)</a></li>
    <li><a href="https://noppa.tkk.fi/">Noppa (an external link)</a></li>
  </ul>

I need to select the links whose targets end with anything (.*), and which do NOT end with (.pdf) and similarly do NOT end with (.html), and apply a CSS class to it. I need to use jQuery for this. I tried to do it with filter, but made a mess of it, as I have just started learning jQuery:

    $("a[href$='.*']").filter(function(){
           $("a[href$!='.pdf']").filter(function(){
                  $("a[href$!='.html']").addClass("download");
            });
     });

I know it's completely wrong, but I can't figure out how to do it. I googled around, but the function() inside filter() is not really clear. Can someone help, please?

Upvotes: 0

Views: 663

Answers (7)

David Thomas
David Thomas

Reputation: 253506

While you say you "need to do this with jQuery," I wanted to offer a plain JavaScript alternative (for yourself or others, in future):

// calls Array.prototype.forEach(), using the array-like NodeList
// returned by document.querySelectorAll(), iterating over that NodeList
[].forEach.call(document.querySelectorAll('li a'), function (aElem) {
    // 'aElem' is the current array-element (the <a>)

    // if the aElem.href property does not (note the '!') end with
    // either 'pdf' or 'html' (RegExp.prototype.test() returns
    // a Boolean)
    if (!(/(pdf|html)$/).test(aElem.href)) {
        // we add the 'download' class to the element:
        aElem.classList.add('download');
    }
});

JS Fiddle link.

Alternatively:

[].forEach.call(document.querySelectorAll('li a'), function (aElem) {
    // if the final part of the href (following the final '.' character)
    // is not found in the array (and thus an index of -1):
    if (['pdf','html'].indexOf(aElem.href.split('.').pop()) === -1) {
        aElem.classList.add('download');
    }
});

JS Fiddle link.

References:

Upvotes: 1

Rick Su
Rick Su

Reputation: 16440

i'm late to the party, minor changes to DemoUser's answer

which takes care of # anchor in the URL

$('a')
    .filter(function() {
        // take care of anchor # in download URL
        return !this.href.match(/\.(pdf|html)(#.*)?$/gi);
    })
    .addClass("download"); //if matched, "download" class is added

Upvotes: 0

adeneo
adeneo

Reputation: 318372

You can combine a regex with some simple tests to filter the anchors

$('a').filter(function() {
    var m = this.href.match(/\.(.{3,4})$/), e = m ? m.shift() : null;
    return e && e.indexOf('/') == -1 && e.match(/(pdf|html)/) == null;
}).addClass('download');

FIDDLE

Upvotes: 2

DannyS3
DannyS3

Reputation: 81

You could also do the following:

$("a").each(function( index ) {
    var href = $(this).attr('href');
    if(!((href.toLowerCase().indexOf(".pdf") >= 0) || (href.toLowerCase().indexOf(".html") >= 0))){
        $(this).addClass("download");
    }
});

Upvotes: 0

philz
philz

Reputation: 1022

$("a[href]").filter(function (i) {
    var href = $(this).attr("href");
    return (href.indexOf(".pdf") == -1 && href.indexOf(".html") == -1);
})
.addClass("download");

Upvotes: 1

Sudhir Bastakoti
Sudhir Bastakoti

Reputation: 100205

you could use filter() as,

$('a')
    .filter(function() {
        //use your required regex to check for link
        return this.href.match(/[^.]*?\.(?!pdf|html)/gi);
    })
    .addClass("download"); //if matched, "download" class is added

Upvotes: 1

Barmar
Barmar

Reputation: 782785

jQuery attribute selectors don't allow wildcards or regexp. But you don't need to use filter to remove the .pdf, you can use a :not selector:

$("a:not([href$=.pdf]):not([href$=.html])").addClass("download");

And when you use .filter(), the function is just supposed to return a boolean (indicating whether that element should be included or not in the result), it shouldn't operate on the elements themselves -- you do that on the value returned by .filter, e.g.

$(selector).filter(function() {
    return ...;
}).addClass("download");

Upvotes: 1

Related Questions