73

I'm matching ASP.Net generated elements by ID name, but I have some elements which may render as text boxes or labels depending on the page context. I need to figure out whether the match is to a textbox or label in order to know whether to get the contents by val() or by html().

$("[id$=" + endOfIdToMatch + "]").each(function () {
    //determine whether $(this) is a textbox or label
    //do stuff
});

I found a solution that doesn't work, it just returns "undefined":

$("[id$=" + endOfIdToMatch + "]").each(function () {
    alert($(this).tagName);
});

What am I missing?

CMPalmer
  • 8,571
  • 5
  • 40
  • 49

9 Answers9

92

Just one jQuery too much:

$("[id$=" + endOfIdToMatch + "]").each(function () {
    alert(this.tagName);
});
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • 12
    Or `$(this).get(0).tagName` – Markus Hedlund Aug 21 '10 at 17:49
  • 5
    @Znarkus: True, but makes no sense. ;) – Tomalak Aug 21 '10 at 21:02
  • 2
    No, not in this case. But if you have a variable with a jQuery object, this would be how you'd have to do it :) – Markus Hedlund Aug 30 '10 at 13:30
  • 2
    No. If you'd have a jQuery object, you'd use `$(anything)[0]`. – Tomalak Aug 01 '11 at 20:17
  • BTW, this can be useful in handling event bubbling where you might be wanting to handle an checkbox INPUT in a TD, yet the TD and the INPUT permit a click. (The TD for the row click, the INPUT for the checkbox click.) You can use tagName to determine which was clicked and use e.preventDefault() and return false in order to cancel the event bubble. – Volomike Jan 07 '12 at 16:37
  • @Volomike: That's what `delegate()` and, as of v1.7, `on()` does more elegantly, I think. – Tomalak Jan 08 '12 at 21:21
  • Moreover, according to this -> http://stackoverflow.com/questions/4878484/different-between-tagname-and-nodename-jquery article, it's recommended to use `nodeName`, for it results in **"better consistency between browsers"**. – MC Emperor Jan 12 '12 at 13:06
  • 1
    @MCEmperor: I don't think that's necessary. You will never deal with attribute nodes as a result of a jQuery operation, so `tagName` (a DOM Level 2 property that is supported consistently, even back to ancient implementations) will work perfectly here. There is no gain in using `nodeName`, but of course it will produce the same result. – Tomalak Jan 12 '12 at 18:28
32

Consider this solution without using each():

var elements = $("[id$=" + endOfIdToMatch + "]");
var vals = elements.is("input").val();
var htmls = elements.is("label").html();
var contents = vals.concat(htmls);

Have a look at the documentation for is.

Christian Davén
  • 16,713
  • 12
  • 64
  • 77
25

you could also use something like this:

if ($(this).is('input:checkbox'))

replace "this" with whatever instance you need and 'checkbox' with whatever input type you need.

kapa
  • 77,694
  • 21
  • 158
  • 175
Jelgab
  • 1,840
  • 19
  • 12
6

First time I've answered my own question. After a little more experimentation:

$("[id$=" + endOfIdToMatch + "]").each(function () {
   alert($(this).attr(tagName));
});

works!

CMPalmer
  • 8,571
  • 5
  • 40
  • 49
  • 3
    Still one jQuery too much. :-) You have the DOM element already with "this", no need to wrap it again! – Tomalak Dec 04 '08 at 20:26
3

tagName what a nice tip. I would like to suggest also to use tagName.toLowerCase() since the value returned depends on the document type (HTML or XML/XHTML).

See: http://reference.sitepoint.com/javascript/Element/tagName

Tom Wayson
  • 1,187
  • 1
  • 12
  • 21
3

in jquery 1.6 use prop()

Example

var el = $('body');

if (el.prop('tagName') === 'BODY') {
    console.log('found body')
}
Community
  • 1
  • 1
reco
  • 459
  • 1
  • 6
  • 13
1

This the best way to Get the element type

function tgetelementType( elmentid )
{

    var TypeName = $('#' + elmentid).get(0).tagName;
    var TypeName2 = $('#' + elmentid).get(0).type;


    if($('#' + elmentid).get(0).tagName== "INPUT")
    {
       return $('#' + elmentid).get(0).type.toUpperCase()
    }
    else 
    {
        return $('#' + elmentid).get(0).tagName.toUpperCase() ; 
    }
}
kapa
  • 77,694
  • 21
  • 158
  • 175
Said
  • 11
  • 1
1
$("[id$=" + endOfIdToMatch + "]").each(function(){
    var $this=jQuery(this),ri='';
    switch (this.tagName.toLowerCase()){
        case 'label':
            ri=$this.html();
            break;
        case 'input':
            if($this.attr('type')==='text'){ri=$this.val();}
            break;
        default:
            break;
    }
    return ri;
})

The question is, what do you intend to do after you've determined the tag name? You could just as easily filter the jquery list using an additional selector combined with .end() to do the same thing:

$("[id$=" + endOfIdToMatch + "]")
    .find("input:text")
    .each(function(){
         /* do something with all input:text elements */
    })
    .end()
    .find("label")
    .each(function(){
        /* do something with label elements */
    })
    .end()

This could still be chained if you needed to do further things with this particular collection of elements...just like the example above.

In either case, you'd have to do something with the values while inside the each() statements

ProtectedVoid
  • 76
  • 1
  • 6
0

Yet another solution, arguably more elegant, is to write two separate functions for each element type:

$("input#" + id).each(function() { alert(this + " is an input"); });
$("label#" + id).each(function() { alert(this + " is a label"); });
jevon
  • 3,197
  • 3
  • 32
  • 40