Home > Mobile >  jQuery review DOM and react
jQuery review DOM and react

Time:02-10

I have a bunch of DIVs which are the feed in a portfolio which has a filtering system which shows and hides the DIVs - this works well - I am adapting this system to look at the DIVs that match the filter clicked on and then style them with a new class with jQuery. CSS nth-of-type does not work, as it recognizes the hidden divs and thus messes up my custom layout, so I need a reliable way of checking the list of DIVs and applying the new class ONLY to those which do not have the inline style "transform: scale(0.001)" applied to them - this inline style is applied by the filtering system which I don't want to mess around with - so am looking for a way of adding a new class to the DIVS which don't have "transform: scale(0.001)" applied each time the filter buttons are clicked.

The classes I want to add are "itemPOS1" to the first div without the transform applied, then "itemPOS2" to the 2nd, etc etc... so the list of DIVS below would look like this on initial load:

<div>Project 1</div>
<div>Project 2</div>
<div>Project 3</div>
<div>Project 4</div>
<div>Project 5</div>

Then after clicking on a filter the list could look like this:

<div>Project 1</div>
<div style="transform: scale(0.001)">Project 2</div>
<div style="transform: scale(0.001)">Project 3</div>
<div>Project 4</div>
<div style="transform: scale(0.001)">Project 5</div>

In which case - the list would then look like this once I have added the new classes to those DIVS which are suitable:

<div >Project 1</div>
<div style="transform: scale(0.001)">Project 2</div>
<div style="transform: scale(0.001)">Project 3</div>
<div >Project 4</div>
<div style="transform: scale(0.001)">Project 5</div>

So, in the front end - the user would just see "Project 1" and "Project 4"....

I cant seem to get this to work well - I was using:

$('div:visible:eq(0)').addClass('itemPOS1');
$('div:visible:eq(1)').addClass('itemPOS2');
$('div:visible:eq(2)').addClass('itemPOS3');
$('div:visible:eq(3)').addClass('itemPOS4');

but its not reliable as sometimes it applies classes to DIVs which have the transform: scale(0.001) applied and thus makes the rendering of the projects wrong as the class names get added incorrectly. I was hoping to find a way to only apply the adding class logic to those divs which did not have "transform: scale(0.001)" applied to them...

I also want to add itemPOS1, 2, 3, 4 and 5 to each 5 DIVs that dont have the inline transform applied - so for example - the 6th DIV that should have the class applied should get itemPOS1 not itemPOS6

Any thoughts?

In essence looking for:

if div does not have transform: scale(0.001) then add class itemPOSX

X starting at 1 for 1st div, then 2 for 2nd... up to 5th, then 6th div has itemPOS1, div 7 has itemPO2 etc...

$('div:visible:eq(0)').addClass('itemPOS1');
$('div:visible:eq(1)').addClass('itemPOS2');
$('div:visible:eq(2)').addClass('itemPOS3');
$('div:visible:eq(3)').addClass('itemPOS4');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>basic set</h2>
<div>Project 1</div>
<div>Project 2</div>
<div>Project 3</div>
<div>Project 4</div>
<div>Project 5</div>
<h2>test set filtered:</h2>
<div>Project 1</div>
<div style="transform: scale(0.001)">Project 2</div>
<div style="transform: scale(0.001)">Project 3</div>
<div>Project 4</div>
<div style="transform: scale(0.001)">Project 5</div>

CodePudding user response:

In your instance :visible won't work as technically it is still not hidden, just really small. use not() instead.

Update from your comment I'm assuming you want to reset the count after 5. For that we can use the styles applied

What I did (roughly)

Here I do some manipulation of your classes and a bit more, show how to select just those (which is your question). NOTE: if you click the second button a second time it gets the NEW first one...

$(function() {
  $("#make-obvious-stuff").on('click', function() {
    // select by those with the style transform
    let these = $("[style='transform: scale(0.001)']");
    // now do some stuff with them
    // show how many:
    $(this).after("<div class='found'>Found:"   these.length   "</div>");
    // give class to first one
    these.first().addClass("make-obvious");
    // wrap those NOT the first one; see them do nothing
    these.not().first().wrap("<div class='wrapped'></div>");
    // does nothing:
    these.not().first().show(); // does nothing
    // remove the transform on first one: NOW we see it.
    these.first().css("transform", "");

  });

  $("#do-stuff").on('click', function() {
    // do what was asked: (but this does little perhaps?
    let these = $("[style='transform: scale(0.001)']");
    these.eq(0).addClass('itemPOS1');
    these.eq(1).addClass('itemPOS2');// this overrides the style with !important (that is a bad pattern to adopt)
    these.eq(2).addClass('itemPOS3');
    these.eq(4).addClass('itemPOS4');
  });
})
.make-obvious {
  border: solid lime 1px;
  background-color: #ffdddd;
  padding: 1rem;
}

.wrapped: {
  border: solid blue 2px;
  padding: 2rem;
  background-color: #ddffdd;
}

.found {
  margin: 1rem;
  padding: 1rem;
  border: 1px solid black;
}

.itemPOS1 {
  background-color: #ddddff;
}
.itemPOS2 {
  background-color: #ffddff;
  transform: scale(1)!important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>basic set</h2>
<div>Project 1</div>
<div>Project 2</div>
<div>Project 3</div>
<div>Project 4</div>
<div>Project 5</div>
<h2>test set filtered:</h2>
<div>Project 1</div>
<div style="transform: scale(0.001)">Project 2</div>
<div style="transform: scale(0.001)">Project 3</div>
<div>Project 4</div>
<div style="transform: scale(0.001)">Project 5</div>
Click me first:
<button id="do-stuff">Do Stuff</button> Click me Second:
<button id="make-obvious-stuff">Make Obvious</button>

CodePudding user response:

This detects if the div is clicked on then if it has the class myClass then it will remove the class myClass and vice versa.

 /* HTML */
 <div id="first" ></div>

 /* CSS */
 #first {width:20px; height:20px; background:red;}
 .myClass {border:1px solid #000;}

 /* jQuery 3.4.1 */
 $(document).on('click','#first',function() {
 if ($('#first').hasClass("myClass")) {
 $('#first').removeClass('myClass');
 } else {
 $('#first').addClass('myClass');
 }
 });

I don't know in your project if some of the other divs are hidden when a choice is made but if they are then you can adapt this by checking for hidden divs then firing off an action like removing a class.

 $(document).on('click','#first',function() {
 if ($('#myotherDiv').is(":hidden")) {
 $('#myotherDiv').removeClass('myClass');
 }
 });

https://jsfiddle.net/hjzqwxr7/

Edit: the CSS for myClass is only there to show visually that it works.

  • Related