Home > OS >  Targeting first instance of generated classes
Targeting first instance of generated classes

Time:06-21

I have tried to get a solution with css only but im starting to think it cannot be done: a list of events its displayed by date, and im trying to create css classes based on the event date. The format of the date class is <div , and they are displayed in ascending order so i ended up with this:

<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>

Is there any way i can display only first unique generated class? In my example i have 2 events for 20-06, one for 21-6 and two for 22-6. Having a hard time achieving something similar to

.event_date_[all-dates] {display:none;}
.event_date_[first-iteration-of-a-date]:first-of-type {display:block;}

So far i was able with jQuery to get only the generated classes, but need to add css only to the first unique class.

jQuery('div[class^="event_date_"]').each(function(i){
                jQuery(this).css("color", "blue");

});

CodePudding user response:

Probhably not the easiest way, but you can just do some grouping on all the elements to find the first of each group and apply css styles to that group

var $elems = jQuery('div[class^="event_date_"]')

var firstofGroup = Object.values($elems.get().reduce( (acc,e) => {
    const cls = e.classList[0];
    acc[cls] ||= [], acc[cls].push(e);
    return acc
},{})).map(x => x[0])

$(firstofGroup).css("color","blue");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>

CodePudding user response:

I think you're right you can't do this just with CSS.

You can identify all the unique classes by finding them and adding them to a Set, then loop through the set using each class and jQuery's :first pseudo-class to do something on the first occurrence of each (in this example, turning them blue, but you can do whatever you need to do to them):

const classes = new Set($('[class^="event_date_"]').map((_, e) => {
    return e.className.match(/event_date_\d{2}-\d{2}-\d{4}/)[0];
}).get());
for (const cls of classes) {
    $(`.${cls}:first`).css("color", "blue");
}

Live Example:

const classes = new Set($('[class^="event_date_"]').map((_, e) => {
    return e.className.match(/event_date_\d{2}-\d{2}-\d{4}/)[0];
}).get());

for (const cls of classes) {
    $(`.${cls}:first`).css("color", "blue");
}
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Alternatively, you could build one big selector by combining those with commas in-between, but it seems harder to read and maintain:

$([...classes].map(
    (cls) => `.${cls}:first`
).join(","))
.css("color", "blue");

Live Example:

const classes = new Set($('[class^="event_date_"]').map((_, e) => {
    return e.className.match(/event_date_\d{2}-\d{2}-\d{4}/)[0];
}).get());

$([...classes].map(
    (cls) => `.${cls}:first`
).join(","))
.css("color", "blue");
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>
<div >
 <div >title event</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

CodePudding user response:

If you could move the date class up one level, to the event container, you can solve this with the adjacent sibling combinator.

So your code would be (I've numbered the events so the effect is more apparent):

.event_date_20-06-2020   .event_date_20-06-2020,
.event_date_22-06-2020   .event_date_22-06-2020 {
    display: none;
}
<div >
 <div>title event 1</div>
</div>
<div >
 <div>title event 2</div>
</div>
<div >
 <div>title event 3</div>
</div>
<div >
 <div>title event 4</div>
</div>
<div >
 <div>title event 5</div>
</div>

  • Related