0

Using pure JavaScript without any library like jQuery, how could I detect if a variable holds a DOM Class or ID?

For example if I pass into a function a value that could be...

var mySelector = ".class-name";

or

var mySelector = "#id-name";

Then based on if mySelector holds a Class or ID I would run

document.getElementsByClassName

or

document.getElementsById

What would be the best way to do this without the use of a library like jQuery or another library?

Wes Cossick
  • 2,923
  • 2
  • 20
  • 35
JasonDavis
  • 48,204
  • 100
  • 318
  • 537

5 Answers5

2

Take a look at document.querySelector or document.querySelectorAll, instead. Both of those can find elements by ID or class (as well as other selectors). querySelector will return 1 element, querySelectorAll will return all elements.

var mySelector = ".class-name", // "#id-name" will also work fine.
elements = document.querySelectorAll(mySelector);

Note that this doesn't work in IE < 8 (see http://caniuse.com/#search=querySelectorAll). A polyfill would be the best way to handle it to add IE7 support.

ryanbrill
  • 1,981
  • 10
  • 13
  • While this is a great solution, it is probably worth noting that this doesn't work on IE < 8... But hopefully we don't worry about that any more (or at least not for much longer). :) – Steve Apr 11 '13 at 21:39
  • Also, browser native query selector implementations are far faster than JavaScript string manipulation. – Travis Watson Apr 11 '13 at 21:41
  • @Steve, `querySelectorAll` has better browser support than `getElementsByClassName`. [Clicky](http://caniuse.com/queryselector) – Travis Watson Apr 11 '13 at 21:42
  • @Steve Good point. I've updated my answer to point this out. If IE7 support is required, a polyfill would be the recommended approach. – ryanbrill Apr 11 '13 at 21:43
  • True, but if two elements have the same `id` (which they **shouldn't**), `querySelectorAll` will return both – Ian Apr 11 '13 at 21:45
  • @Steve, It's IE8 that you're missing. 8 supports querySelectorAll, but not getElementsByClassName – Travis Watson Apr 11 '13 at 21:53
  • This is clearly debatable but I choose this answer as the best lightweight solution for my current need. Obviously for anything important I would use jQuery or Sizzle but I really like this newer JS method – JasonDavis Apr 11 '13 at 22:09
  • @jasondavis, You might peek at [this SO question](http://stackoverflow.com/a/11503576/897559) for some more information. – Travis Watson Apr 12 '13 at 14:19
2

You can use this simple if/else statement to differentiate. This would also allow you to run other code based on whether it's a class or an ID you are referencing.

var mySelector = ".class-name";

if(mySelector.charAt(0) == ".")
{
    document.getElementsByClassName(mySelector.substring(1));
}
else if(mySelector.charAt(0) == "#")
{
    document.getElementsById(mySelector.substring(1));
}
Wes Cossick
  • 2,923
  • 2
  • 20
  • 35
  • Why not `mySelector.charAt(0)`? – Ian Apr 11 '13 at 21:39
  • @Ian, yes that would also work. Really just comes down personal preference. – Wes Cossick Apr 11 '13 at 21:41
  • True, but `charAt` is far faster (although probably unnoticeable), and semantically makes more sense. Still, personal preference is the factor – Ian Apr 11 '13 at 21:44
  • Note that getElementsByClassName doesn't work in IE8 and below. http://caniuse.com/#search=getElementsByClassName – ryanbrill Apr 11 '13 at 21:45
  • @Ian Might as well change it to `charAt`. It does entail a few less characters of code. – Wes Cossick Apr 11 '13 at 21:46
  • @Ian, not that unnoticeable [http://jsperf.com/sunsean-substr-charat](http://jsperf.com/sunsean-substr-charat) – Travis Watson Apr 11 '13 at 21:46
  • @Travis True (and I've looked at http://jsperf.com/substr-or-charat ) but what I meant by "unnoticeable" was that I doubt you'll actually notice that difference when the code is running...unless the code is executed rapidly or in a loop – Ian Apr 11 '13 at 21:48
1

The first way I think is check a first symbol of stroke. Something like:

var $ = function( string ) {
  var result;
  switch (string.substr(0,1)) {
    case '.': result = document.getElementsByClassName(string); break;
    case '#': result = document.getElementById(string); break;
    default: result = document.getElementsByTagName(string); break;
  }
  return result;
}
var mySelector = ".class-name";
console.log( $(mySelector) );
Novelist
  • 469
  • 4
  • 15
1

Just because you only want a selector and not the entire jQuery library, doesn't mean you have to roll your own own. jQuery uses the Sizzle selector engine, and you could just as easily use it yourself without the overhead of full jQuery:

http://sizzlejs.com/

Travis Watson
  • 1,729
  • 1
  • 18
  • 25
0

I'm not an advanced user, but some time ago I created this little script:

https://gist.github.com/caiotarifa/cc7d486292f39157d763

var __;

__ = function(selector, filter) {
  'use strict';

  var response;

  function filtering(selectors, filter) {
    switch (filter) {
      case "first":
        return selectors[0];
        break;
      case "last":
        return selectors[selectors.length - 1];
        break;
      default:
        return selectors[filter];
        break;
    }
  }

  selector = selector.trim();
  if (typeof filter === "string") { filter = filter.trim(); }

  if (selector.indexOf(' ') < 0 && selector.indexOf('.', 1) < 0 && selector.indexOf('#', 1) < 0) {
    switch (selector.substr(0, 1)) {
      case '.':
        response = document.getElementsByClassName(selector.substr(1));
        if (response.length === 1) { filter = "first"; }
        if (typeof filter !== "undefined") { response = filtering(response, filter) }
        break;
      case '#':
        response = document.getElementById(selector.substr(1));
        break;
      default:
        response = document.getElementsByTagName(selector);
        if (response.length === 1) { filter = "first"; }
        if (typeof filter !== "undefined") { response = filtering(response, filter) }
        break;
    }
  } else {
    if (typeof filter !== "undefined") {
      switch (filter) {
        case "first":
          response = document.querySelector(selector);
          break;
        case "last":
          response = document.querySelectorAll(selector);
          response = response[response.length - 1];
          break;
        default:
          response = document.querySelectorAll(selector);
          response = response[filter];
          break;
      }
    } else {
      response = document.querySelectorAll(selector);
      if (response.length === 1) { response = response[0]; }
      else if (response.length < 1) { response = false; }
    }
  }

  return response;
};

It's simple to use it:

__("div")

Or passing some filter like:

__("div", "first")

I didn't make a benchmark test with it. I hope it can help you.

Caio Tarifa
  • 5,973
  • 11
  • 46
  • 73