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

10

Class selectors such as .exemplo or selectors separated by [atributo~=valor] te% behave totally differently than selectors like:

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

The .exemplo and [atributo~=valor] seek values separated by spaces. What I need is a custom selector with jQuery.expr to fetch values separated by spaces, but you can use similar character to % of LIKE in mysql ( link ).

The idea is to do something like (similar):

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

Or similar:

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

It would take any class that had js-use-2 , js-use-palavraqualquer , js-use-3 , etc.

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

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

Or

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

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

  

Note: The selector per point ( . ) does not only get attributes like <div class="foo"> , it also takes <div class="alpha foo betha"> , that is, it takes the attribute divided by "space".   More details on link

Is this possible with jQuery?

    
asked by anonymous 17.07.2015 / 00:56

4 answers

2

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

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

  
    

Note: The selector per point ( . ) does not only get attributes like <div class="foo"> , it also takes <div class="alpha foo betha"> , that is, it takes the attribute divided by "space". More details on link

  

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

The solution

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

The solution I came up with will behave like .class or how, it looks like this:

//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><!--abaixoserácomoseletor:class-wildcard(js-use-?)--><divclass="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 divides strings into arrays like this:

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

This way you can apply "escape" to characters that could affect the occurring within for() :

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

So then it joins with .join the arrays again using as a separator the \S+ which will be the wildcard in this case, the expression \S ("s" in upper case) is the negation of \s ie the wildcard can be anything but space, tab or line break.

Note that we also used \b on the ends, an expression like this:

\bfoobar\b

It would be "similar" to this:

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

That is, the value tested in the regex should begin and end with the expression word, or should contain spaces.

Then after join the parameters would have results like this:

  • js-use-? flip this regex /\bjs-use-\S+\b/
  • foo?bar flip this regex /\bfoo\S+bar\b/
  • a?b?cde?xyz? flip this regex /\ba\S+b\S+cde\S+xyz\S+\b/
16.08.2018 / 03:34
7
Note: I have no idea what "wildcard" means, but I will use that word in the example of this answer.

jQuery does not do this naturally. But you can extend the : pseudo selector to do this.

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

jQuery gauzes 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 that pseudo-selector as the last argument.

The code to do this would look 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 use this:

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

jsFiddle: link

    
17.07.2015 / 10:12
0

You can do this the way it 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 is the jsFiddle: link

    
20.08.2015 / 19:48
0

As already stated, jQuery uses the selectors you mentioned:

^= starts with (start with); $= ends with (end with); (contains);

Natively these are, but there are extensions that allow you to use wildcards, such as this: jquery-wildcard-selector

Lets you do things like:

*=

And in your example, selecting a class (as in the question: $(':withWildcard(name, foo-*-*)') looks like this: $(".js-use-?")

    
09.08.2018 / 21:44