1

Is there a better way to do this in jQuery? Depending on the end part of a href I'm running some code. The current version sure is ugly...

$(document).ready(function(){

    $('a[href$="pdf"], a[href$="zip"], a[href$="doc"], a[href$="docx"], a[href$="xls"], a[href$="xlsx"], a[href$="ppt"], a[href$="pptx"], a[href$="mp3"], a[href$="txt"], a[href$="vsd"], a[href$="rar"], a[href$="wma"], a[href$="avi"], a[href$="mmv"]').bind("click", function() {
        // do processing here
    });

});

I am unable to add ID or class attributes as the html is generated by a CMS

James Wiseman
  • 29,946
  • 17
  • 95
  • 158
Rob
  • 1,688
  • 4
  • 30
  • 43
  • 3
    One thing to note. That `a` only applies to the first condition. Not that you'll have non-a elements which have an href, but you should probably add the `a` to each to be consistent. – James Montagne Aug 08 '11 at 13:43
  • 1
    The answers to this question are testament to the ingenuity of SO users. The 6 answers at the time of writing were all so very different. – James Wiseman Aug 08 '11 at 13:55

6 Answers6

0

Your selector is wrong and also instead of selecting so many elements try this

//this will attach click event only to 
$(document).ready(function(){

    $('a').live('click', function() {//Use any class name associated to this anchor or an id to select it

       //this.href will give the href of the anchor which is clicked.
       //check for href contians the required extension or no by writing a switch block or if/else conditions

      var extn = (/[.]/.exec(this.href)) ? /[^.]+$/.exec(this.href) : undefined;
      if(extn)
         extn = extn[0];

       // do processing here
       switch(extn.toLowerCase())
       {
          case "pdf" :
               break;
          case "zip" :
               break;

          ...
          ...

       }

    });

});
ShankarSangoli
  • 69,612
  • 13
  • 93
  • 124
0

Ever consider externalizing the selectors from the logic?

var x = new Array(); 
x = ['pdf', 'zip', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'mp3', 'txt', 'vsd', 'rar', 'wma', 'avi', 'mmv']; 

for (y in x)
{
    $('a[href$="'+y+'"]').click(function()
    {
        // do processing here
    });
}
k4t434sis
  • 519
  • 4
  • 17
  • great solution, slight typo though - i've amended to x[y] – Rob Aug 08 '11 at 14:02
  • This is not a great solution. as it will attach click event for all the anchors if it finds. Check my solution it uses only one event handler even if you have 100 anchors on the page. – ShankarSangoli Aug 08 '11 at 14:07
  • 1
    Generally not a good idea to use `for .. in` on an array http://stackoverflow.com/questions/500504/javascript-for-in-with-arrays or to use `new Array()`. – James Montagne Aug 08 '11 at 14:12
  • @ShankarSangoli it would attach the click event to all anchors of the specified types... doc, docx etc – Rob Aug 08 '11 at 14:53
  • @Rob - That can be avoided if you use live or delegate. With only one event handler all the types can be handled. Check my solution. – ShankarSangoli Aug 08 '11 at 15:03
0

You could try a custom selector. So given the correct code you could do something like:

$('a:HrefMatch').click(function(){
});

And the implementing selector code might look something like

$.extend($.expr[':'], {  
    HrefMatch: function(elem) {  
        var elemHref= $(elem).attr("href");
        var searchRegex = /((pdf)|(zip)|(doc)|(docx)|(xls)|(xlsx)|(ppt)|(pptx)|(mp3)|(txt)|(vsd)|(avi)|(mmv))$/
        return elemHref.test(searchRegex);  
    }  
}); 

(I haven't quite inlcuded all the doc types in the regex, but you could happily include them yourself)

Also, I've separated the selector out into 3 lines of code. It could just as easily be:

$.extend($.expr[':'], {  
    HrefMatch: function(elem) {  
        return $(elem).attr("href").test(/((pdf)|(zip)|(doc)|(docx)|(xls)|(xlsx)|(ppt)|(pptx)|(mp3)|(txt)|(vsd)|(avi)|(mmv))$/);  
    }  
}); 
James Wiseman
  • 29,946
  • 17
  • 95
  • 158
0
$(document).ready(function(){
    var extensions = ["doc", "xls", "ppt"]; // can extend this
    $('a').filter(function() {
        var href = $(this).attr('href');
        for(var i = 0; i < extensions.length; i++) {
            if(href.substring(href.length - extensions[i].length) == extensions[i]) {
                return true;
            }
        }
    }).bind('click', function(){

    });

});
Dogbert
  • 212,659
  • 41
  • 396
  • 397
0

Try "data-" attribute.

Your code would look like this:

<div class="files">
    <a href="file.pdf" data-extension="pdf">filename.pdf</a>
    <a href="file.zip" data-extension="zip">filename.zip</a>
</div>

Javascript:

$('div.files a').bind("click", function() {
       // do processing here
       var extension = $(this).data("extension");
});
Erik Márföldi
  • 206
  • 1
  • 2
  • 10
0

What about:

$('a:not[href$="htm"]')

Obviously swap out htm for whatever extension is standard on your site.

Richard Dalton
  • 35,513
  • 6
  • 73
  • 91