3

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;
  }
});
4
  • Why don't you use e.g data-transition="left" attribute? Normally I would use a data attribute data-in="left", but can't for this project. How that? Commented Aug 22, 2015 at 11:46
  • 2
    If you know all the class names, you could use a switch check, or just use $(this).attr('class') in your .each function to find all of the classes it has. Commented Aug 22, 2015 at 11:46
  • While the hasClass() approach is probably easiest, what sort of result did you want from the function you were trying to put together? An Object containing the Node and the 'full class'? Or a 2 dimensional array of some kind? Commented Aug 22, 2015 at 11:52
  • @Woff. I am adding a custom intro outro effects to 'Layer Slider' plugin for Wordpress. And the plugin Author only allows you to add classes to each slide not data attributes, so I am confined by that. Commented Aug 22, 2015 at 12:21

3 Answers 3

4

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() ... */
});
Sign up to request clarification or add additional context in comments.

4 Comments

I agree that this should work well, but it presupposes you always know all of the class options ahead of time.
Well, I was basing my answer to the given information.. ^^
Yeah the user will be inputting these exact names, else it won't work or they will get a default chosen for them. I am wondering if hasClass with the if else chain will be expensive though. There shouldn't be anymore than 3 items being animated in at any one time however.
I think it will perform just fine, plus it would be more readable, no?
2

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:

2 Comments

Thanks David, I implemented Toni's answer it's working good. I had thought before I posted my question about taking the class names and converting them to data attributes like you mentioned, but for the sake of performance I decided to go this way. But now that you brought it up again might actually be a good way to go. There is an event that fires on the slider init() where I could do the conversions to data attributes and then my code will run faster on the slide in and slide out events. hmm ;)
No worries, and you are very welcome indeed! Note that I do recommend Toni's answer (simply for ease of use), but I left this solution almost purely to address the fundamental question you asked (and because it was fun to solve). In future, though, I'd advise that you take a little more time to specify your required/expected result - because being asked to find the 'full class name' is easy enough to do, but I had no idea where you wanted it to be returned (hence I used the data-* attribute purely as a demonstration of how to find/use that found class-name.
1

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

5 Comments

This presumes that the in- prefixed class-name will always be the second class-name in the class attribute; this seems an unrealistic assumption, despite that being true in the demo.
Yes, its will answer acc. to the html in question, i have another solution with some modification in this for weather is it first class or second class. I will edit my answer.
Check my edited answer and jsfiddle, there is html div where in- contain class also at first place. jsfiddle.net/4aksdj3a
Umesh, do you think this approach would be less expensive than using hasClass?
I can say that switch case statement is better approach than if else statment. Switch case jump directly to matched case, but if statement check every condition whenever not matched.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.