How to use "wildcard" in "CLASS" selectors with jQuery.expr?

Asked

Viewed 1,737 times

11

The class selectors as .exemplo or sorted selectors by spacing [atributo~=valor] behave totally different from selectors like:

  • [atributo=valor]
  • [atributo*=valor]
  • [atributo^=valor]

The .exemplo and [atributo~=valor] search for values separated by spaces. What I need is a custom selector with jQuery.expr to search for space-separated values, but it is possible to use character wildcard similar at the % of LIKE in mysql (https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like).

The idea is to do something like (similar):

$(".js-use-?").length //Retorna 4

Or similar:

$("[class~=js-use-?]").length //Retorna 4

He’d take any class I ever had js-use-2, js-use-palavraqualquer, js-use-3, etc..

In case the ? will be the wildcard, but you could use % also, for example:

$(".js-use-%").length //Retorna 4

Or else

$(".foo-%-hello").length

The character wildcard is irrelevant, can be anything, provided that the behavior of values separated by spaces is the same as the selectors already mentioned .exemplo and [atributo~=valor]

Note: the selector per point (.) not only takes attributes such as <div class="foo">, he takes too <div class="alpha foo betha">, In other words, it takes the attribute divided by "space". More details on http://www.w3.org/TR/css3-selectors/#class-html

This is possible with jQuery?

  • Officially jQuery supports CSS3 selectors, which are the ones you already know. Unfortunately there are no wildcards (wildcards) in these selectors, so this feature is not officially supported. However, I found this extension here that can serve you, it uses Regex (Regular Expressions): http://james.padolsey.com/javascript/regex-selector-for-jquery/.

  • Check out this answer: http://stackoverflow.com/a/190255/1161005

4 answers

7

Note: I have no idea what "joker" means but I will use that word in the example of this answer.

jQuery doesn’t do it naturally. But it can extend the pseudo selector : to do this.

The functionality could be: :coringa(<atributo>, <string com "?">).

jQuery gauarda methods for pseudo selectors in jQuery.expr[':'] and you can create a new simple by creating a new property on that object.

This new method is passed by Sizzle/jQuery the element, the index between its siblings and what is inside this pseudo-selector as the last argument.

The code to do that would be like this:

jQuery.expr[':'].coringa = function(elem, index, match) {
    var parametros = match[3].split(' ').join('').split(',');
    var attr = parametros[0];
    var regexString = parametros[1].replace('?', '([a-zA-Z_\\-0-9]+)');
    var regex = new RegExp(regexString, 'ig');
    return regex.test(jQuery(elem).attr(attr));
}

And then wear it like this:

$(':coringa(class, js-?-empty)').css('color', 'red');

jsFiddle: http://jsfiddle.net/9br4Lt3p/

  • 2

    Joker is the same as Joker: Character, usually an asterisk (), which may represent any other character*

  • 1

    http://portuguese.stackexchange.com/questions/425/curinga-or-coringa

  • Joker is widely used in Brazil, by adaptation because of the character of Batman, but the correct is wildcard, already correct the title in the question.

  • Haha, this pt.se will come in very handy here :) We could open a branch there for code terms :)

  • Sérgio, I am really grateful, your answer passed a little close, but honestly it is not the behavior of the class selector, so I ended up writing a response https://answall.com/a/322698/3635

  • 1

    @Guilhermenascimento I saw only now your answer, I had no time before to see more carefully. ++

Show 1 more comment

2


Unfortunately all other answers are wrong, managed the wildcard/wildcard behavior, but did not understand that the behavior has to be as is the selector .classe, just as it is in CSS2, CSS2.1 and CSS2.2

Both the selector .classe how much the attribute selector [atributo~=valor] do not behave like normal attribute selectors, I explained and stressed that well in the question, at this point:

Note: the selector per point (.) not only takes attributes such as <div class="foo">, he takes too <div class="alpha foo betha">, i.e., it takes the attribute divided by "space". More details on http://www.w3.org/TR/css3-selectors/#class-html

Aliais follows the basic documentation link for those who are learning CSS and want to understand the differences (or confirm what I say):


The solution

To make a selector that behaves like the class selector (or this selector [atributo~=valor]) of CSS with character wildcard similar to the % of LIKE in Mysql

The solution I arrived at will behave as .class or how , was so:

//Seletor customizado
jQuery.expr[':']['class-wildcard'] = function (elem, index, match) {

    //Separa as partes da string
    var parse = $.trim(match[3]).split('?');

    //Escapa os caracteres necessários
    for (var i = 0, j = parse.length; i < j; ++i) {
        parse[i] = parse[i].replace(/[-\][*+?)(:\\]/g, '\\$&');
    }

    // Gera a regex em formato de string
    var cls = '\\b' + parse.join('\\S+') + '\\b';

    return new RegExp(cls).test(elem.className);
};

console.log(":class-wildcard(js-use-?) -> ", $(":class-wildcard(js-use-?)").length);

console.log(":class-wildcard(foo?bar) -> ", $(":class-wildcard(foo?bar)").length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<!-- abaixo será com o seletor :class-wildcard(js-use-?) -->
<div class="foo js-use-1"></div>     <!-- será pego -->
<div class="js-use-2 bar"></div>     <!-- será pego -->
<div class="baz js-use-3 boo"></div> <!-- será pego -->
<div class="js-use-empty"></div>     <!-- será pego -->

<div class="foo wjs-use-1"></div>     <!-- NÃO será pego -->
<div class="xjs-use-2 bar"></div>     <!-- NÃO será pego -->
<div class="baz yjs-use-3 boo"></div> <!-- NÃO será pego -->
<div class="zjs-use-empty"></div>     <!-- NÃO será pego -->


<!-- abaixo será com o seletor  :class-wildcard(foo?bar) -->
<div class="foobazbar"></div>             <!-- será pego -->
<div class="fooxyzbar"></div>             <!-- será pego -->
<div class="fooabcbar"></div>             <!-- será pego -->
<div class="col1 foobazbar"></div>        <!-- será pego -->
<div class="col2 fooxyzbar custom"></div> <!-- será pego -->
<div class="fooabcbar col3"></div>        <!-- será pego -->
<div class="fooar col4"></div>            <!-- NÃO será pego -->

Explaining the code

To better explain the code, parse splits strings into arrays, thus:

  • js-use-? flipped ["js-use", ""]
  • foo?bar flipped ["foo", "bar"]

This way it is possible to apply the "escape" in characters that could affect the which occurs within the for():

parse[i] = parse[i].replace(/[-\][*+?)(:\\]/g, '\\$&');

Then he joins with .join the arrays again using as separator the \S+ which will be the wildcard/wildcard in the case, the expression \S ("s" in capital letters) is the negation of \s, ie the joker can be anything but space, tab or line break.

Note that it was also used \b at the ends, such an expression:

\bfoobar\b

Seria "similar" to this:

(^|\s)foobar($|\s)

That is, the value tested in regex must start and end with the word of the expression, or must contain spaces.

Then after the join the parameters would have results like this:

  • js-use-? turns this regex /\bjs-use-\S+\b/
  • foo?bar turns this regex /\bfoo\S+bar\b/
  • a?b?cde?xyz? turns this regex /\ba\S+b\S+cde\S+xyz\S+\b/
  • 1

    +1 for the clarification

0

You can do it this way that also works:

$(function() { 
    $('div').each(function() {
               var classes = $(this).attr('class');
               var arrClass = classes.split(' ');
                   arrClass.forEach(function(value, key) {
                      if ( value.indexOf('js-use') !== -1) {
                         $('.'+value).css('color','red');
                      }
                  });
    });
});

Here the jsFiddle: http://jsfiddle.net/ivanferrer/9br4Lt3p/2/

0

As already replied, the jQuery uses the selectors you mentioned:

^= Starts with (start with);
$= ends with (end with);
*= contains (contains);

Natively these are, but there are extensions that allow you to use wildcards, or wild cards, like this one for example: jquery-wildcard-selector

Allows you to do things like:

$(':withWildcard(name, foo-*-*)')

And in your example, selecting a class (how is the question: $(".js-use-?") gets like this: $(':withWildcard(class, js-use-*)')

  • 1

    Dear Ricardo I want to solve for classes and not for attributes, the behavior is different. I wrote in the reward: "I await more suggestions that of preference behave as class and not as attribute", So classes don’t behave like attributes, what I want is something else. Please if you can edit the answer to what is asked in the question I would be grateful.

  • @Guilhermenascimento, I had put an example but it was not clear, I edited the question and put the specific example for one selector per class, please see if it is what you are looking for but prepare another example. Thanks for pointing out

  • Dear Ricardo, the problem is that class is not an attribute, the way you have behaved as an attribute, can you understand how "class selector" works? Do you know that it works very different from attribute selector right? Do not just pass :withWildcard(class ai the behavior is as an attribute normal, no use at all with what is asked in the question, the only CSS selector (and querySelector) is the [atributo~="..."]. Maybe this will help you get an idea.

  • Yes understood @Guilhermenascimento, really ends up behaving different, even more you need to join something like + elemento or > elemento won’t work properly

  • I’m grateful for your attempt, but your response has gone nowhere near, from what I’ve already said, this $(".js-use-?") is not the same thing as $(':withWildcard(class, js-use-*)'), the behaviour is totally different, I have prepared a response https://answall.com/a/322698/3635, if you are interested.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.