Benjamin
Benjamin

Reputation: 697

jQuery find full class name using partial string

I have slides with varying class names 'in-left' 'in-right' 'in-bottom' ect. I need to first find any slide that has a class starting with 'in-' but then I need to get the full class name 'in-left' to use for a switch statement. I am trying to find the most efficient way to do this, hopefully without a regex?

Normally I would use a data attribute data-in="left", but can't for this project.

<div class="container">
    <div class="slide in-left"></div>
    <div class="slide in-right"></div>
    <div class="slide in-bottom"></div>
    <div class="slide in-top"></div>
</div>

jquery

var $els = $('.slide[class*="in-"]');
$.each( $els, function(k, v){
  var type = v; // Get full class name for classes that start with 'in-'
  switch (type) { 
    case 'in-left':
      // Transition in from left
    break;
    case 'in-bottom':
      // Transition in from bottom
    break;
  }
});

Upvotes: 3

Views: 2687

Answers (3)

David Thomas
David Thomas

Reputation: 253318

While I would strongly advise that you go with Toni's answer, I wanted to offer an alternative solution to the problem, even thought it's not quite what you were asking for – though that's because you offered no clarity, or explanation, of where you wanted the 'full class-name' returned to.

This approach takes the prefixed class-names and then creates a data-* attribute on each element with the prefix-name; therefore the classes with the prefix of "in-" are used to generate a data-in attribute with the suffix of the class, following the '-' character becomes the attribute-value. So:

<div class="in-left"></div>

Becomes:

<div class="in-left" data-in="left"></div>

Which seems to be an appropriate solution to the problem you describe, and allows you to use your 'normal'/'preferred' syntax to access the relevant elements; though there's some ambguity and a lack of clarity of the desired result in your question as it stands.

That said, one approach is the following:

// creating a simple jQuery plugin:
(function ($) {

    // the plugin-name:
    $.fn.fullClassFromPartial = function (opts) {

        // extending the 'defaults' with the
        // options supplied by the user:
        var s = $.extend({
            'partial': '',
            'join' : ''
        }, opts);

        // we proceed only if the user supplies a
        // value for the s.partial property:
        if (s.partial.length) {

            // returning the jQuery collection (this),
            // after iterating through that collection
            // using the each() method:
            return this.each(function (i, n) {

                // setting the data-* attribute equal
                // to the value of the s.partial value
                // after replacing non-alpha characters:
                n.dataset[s.partial.replace(/[^a-z]/g, '')] =

                   // setting the attribute-value, first
                   // using Function.prototype.call() to
                   // allow us to use Array.prototype.slice()
                   // on the Array-like return-value of
                   // the HTMLElement.classList property
                   // to convert the Array-like value into
                   // an Array:
                   Array.prototype.slice.call(n.classList, 0)

                       // using Array.prototype.filter()
                       // to retain only those elements
                       // upon whom the inner assessment
                       // returns a true/truthy value:
                       .filter(function (cN, i) {
                           // within the anonymous function the
                           // first argument ('cN') is the array
                           // element of the array over which
                           // we're iterating; the second argument
                           // ('i') is the index of that array-element
                           // in the Array.

                               // if the s.partial value is found at
                               // the beginning of the array-value,
                               // we retain this element in the array:
                               return cN.indexOf(s.partial) === 0;

                            // we convert into a map, using
                            // using Array.prototype.map()
                            // in order to create/return a new
                            // Array:
                            }).map(function (cN) {

                                // here we return the class-name
                                // after removing the s.partial
                                // prefix from it:
                                return cN.replace(s.partial, '');

                // should multiple attribute-values prefixed with
                // the same string exist, then we join them together
                // with the value supplied to the s.join property
                // which can be updated by the user via the 
                // supplied options:
                }).join(s.join);
            });

        // 
        } else {
            return this;
        }
    };

})(jQuery);

// calling the plugin (note that while I haven't restricted
// the selector to only those elements whose class contains
// the 'in-' string, that is definitely recommended (this is
// just a simple demo, though, and I want to show it working
// with a larger-than-necessary collection):
$('div').fullClassFromPartial({

    // setting the 'partial' property to the prefix
    // we're looking for:
    'partial': "in-",

    // setting the 'join' property to the string
    // with which we want to join multiple values
    // together:
    'join' : '_'
});

(function($) {
  $.fn.fullClassFromPartial = function(opts) {
    var s = $.extend({
      'partial': '',
      'join': ' '
    }, opts);

    if (s.partial.length) {
      return this.each(function(i, n) {
        n.dataset[s.partial.replace(/[^a-z]/g, '')] = Array.prototype.slice.call(n.classList, 0).filter(function(cN, i) {
          return cN.indexOf(s.partial) === 0;
        }).map(function(cN) {
          return cN.replace(s.partial, '');
        }).join(s.join || ' ');
      });
    } else {
      return this;
    }
  };

})(jQuery);

$('div[class*="in-"]').fullClassFromPartial({
  'partial': "in-",
  'join': '_'
});
div {
  border: 2px solid #000;
  min-height: 2px;
  margin: 1em;
  padding: 0.5em;
}
[data-in]::before {
  content: attr(data-in);
}
[data-in=left] {
  border-left-color: #f90;
}
[data-in=right] {
  border-right-color: #f90;
}
[data-in=top] {
  border-top-color: #f90;
}
[data-in=bottom] {
  border-bottom-color: #f90;
}
[data-in=top_left] {
  background-color: #ffa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="slide in-top"></div>
  <div></div>
  <div class="slide in-right"></div>
  <div class="left"></div>
  <div class="slide in-bottom"></div>
  <div class="in-bottom slide"></div>
  <div class="slide in-left"></div>
  <div class="slide in-top in-left"></div>
</div>

External JS Fiddle demo, for experimentation and development.

References:

Upvotes: 2

Toni Michel Caubet
Toni Michel Caubet

Reputation: 20163

How about, if you know the possible values, to use hasClass

$('.slide').each( function(){
  var $this = $(this);
  if ($this.hasClass('in-left')) {

  } else if ($this.hasClass('in-bottom')) {

  } /* else if() ... */
});

Upvotes: 4

Umesh Sehta
Umesh Sehta

Reputation: 10683

You can do with this:

var $els = $('.slide[class*="in-"]');
$.each( $els, function(k, v){

  var type ='';
    type = $(this).attr('class').split(' ')[1];
  if(type.indexOf('in-')==-1)
    type = $(this).attr('class').split(' ')[0];

  switch (type) { 
    case 'in-left':
      // Transition in from left
    break;
    case 'in-bottom':
      // Transition in from bottom
    break;
  }
});

This will solve your problem. Click here jsfiddle

Upvotes: 1

Related Questions