Laurent
Laurent

Reputation: 1563

jQuery - create groups of elements based on attribute values

I'm trying to figure out the best way to create groups of elements based on common properties. I can obviously compare them one by one and end up with the correct result but I'm sure there is a better way to go.

So, I basically assign 4 types of attributes to my divs: position top, position left, width and position bottom. I have 4 divs to which I assign them (but 4 may be bigger in the future).

zones = 4;
for (x = 1; x<=zones ; x++)
    {
        $('#zone'+x).attr('data-top',Math.floor($('#zone'+x).position().top));
        $('#zone'+x).attr('data-bottom',Math.floor($('#zone'+x).position().top) + $('#zone'+x).height());
        $('#zone'+x).attr('data-left',Math.floor($('#zone'+x).position().left));
        $('#zone'+x).attr('data-width',$('#zone'+x).width());
    }   

With this I end up with something like this:

<div id="zone2" data-top="976" data-bottom="2579" data-left="131" data-width="660">...</div>

Now the challenge I'm facing is to create groups of elements based on all divs that have a common data-top value. The simple solution was to compare all data-top to each other, while with only 4 divs to compare it's manageable but if the number of divs grow, it will soon become a mess.

QUESTION 1: how to assign a group for a common attribute value?

What I'm trying to get in the end is:

<div id="zone2" data-top="976" data-bottom="2579" data-left="131" data-width="660" data-group="1">...</div>

And data-group would be equal to 1 for all divs that have the same data-top value. If there are multiple groups sharing common data-top values, then I would need data-group to be incremented. I could end up with something like this:

<div id="zone1" data-top="976" data-bottom="2379" data-left="131" data-width="660" data-group="1">...</div>
<div id="zone2" data-top="976" data-bottom="2579" data-left="131" data-width="660" data-group="1">...</div>
<div id="zone3" data-top="1500" data-bottom="2479" data-left="131" data-width="660" data-group="2">...</div>
<div id="zone3" data-top="1500" data-bottom="3579" data-left="131" data-width="660" data-group="2">...</div>

QUESTION 2: how to find a maximum value within a group ?

With the groups correctly set, how should I proceed to find the maximum data-bottom value? In the example above, the maximum data-bottom value for data-group=1 is 2579 and 3579 for data-group=2

I thought of using .each and within the .each compare values, it works in the end but code is awfully long.

Upvotes: 3

Views: 2020

Answers (1)

kapantzak
kapantzak

Reputation: 11750

I would propose this approach (FIDDLE)

First, set a data attribute (data-zone) for each element. Then iterate over the elements and call getTopGroup() function to check if this group exists and assign the data-group-top attribute.

HTML

<div class="zone1" data-zone="1">Zone 1</div>
<div class="zone2" data-zone="2">Zone 2</div>
<div class="zone3" data-zone="3">Zone 3</div>
<div class="zone4" data-zone="4">Zone 4</div>
<div class="zone1" data-zone="1">Zone 1</div>
<div class="zone2" data-zone="2">Zone 2</div>
<div class="zone3" data-zone="3">Zone 3</div>
<div class="zone4" data-zone="4">Zone 4</div>

jQuery

// Create a blank array of groups
var groupsTop = [];

var getTopGroup = function(top) {
  var group = 1;
  var groupIndex = $.inArray(parseInt(top), groupsTop);      
  if (groupIndex == -1) {
    groupsTop.push(top);
    return groupsTop.length;
  } else {
    return groupIndex + 1;
  }
};

$('[class^=zone]').each(function() {
    var elem = $(this);
  var x = elem.attr('data-zone');
  var top = 10* x;
  var topGroup = getTopGroup(top);
  // This is an example calculation of offsets
  elem.attr({
    'data-top': top,
    'data-bottom': 5 * x,
    'data-left': 3 * x,
    'data-width': 6 * x,
    'data-group-top': topGroup
  });
});

You can use the same logic to implement a check for other data attributes too.

Upvotes: 1

Related Questions