简体   繁体   中英

jQuery checking each element against each other element in a class

(ty putvande and shanet for pointing out the wrong ')' which now is removed, I had however to repost the question as it only got answers related to that little mistake and not the main question)

I'm having a lot of difficulties constructing the following in javascript:

FOR every element with Assemble_station class

CHECK whether it overlaps with each other element with Assemble_station class

IF it does: CHECK which element has biggest left position of the two, move the element with the biggest left position to another location to avoid collision

Here's what I've written

$(".Assemble_station").each(function (i, firstobj) {
    $(".Assemble_station").each(function (i, secondobj) {
        if ($(firstobj).overlaps($(".Assemble_station").not(firstobj), secondobj)) {
            if ($(firstobj).css("left") >= $(secondobj).css("left")) {
                $(secondobj).css("top", "98px");
            }
        }
    });
});

Here's a jsfiddle that uses the code at the back: http://jsfiddle.net/NxWxU/6/

To sum up the question, I'm trying to find the best practice method for doing what I described above. And so far I don't get why my current code isn't even working. >.<

You can see that some of the elements clearly overlap if you break my code in jsfiddle and watch their positions before the are moved to same vertical position.

Ty for taking the time to try help

Suggestions to improve your coding and debugging skills

Your updated code (in which you resolved the lack of the overlaps function) is failing because jQuery plugins are not supposed to be used in that way. Please consider reading about creating jQuery plugins , and as much as you can about javascript debugging before trying to resolve this kind of problem.

Try to develop your debugging abilities by doing all of the following in the console after setting breakpoints (or using the debugger statement in your code):

  • Play the relevant code step by step
  • Check variables values
  • Go thru the stacktrace
  • Put commands in the console to see how the code behaves in that context

For instance, to resolve this problem I used some jQuery into the console :

> $(".Assemble_station") // this returned elements with [visibility:hidden] so I tried:
> $(".Assemble_station:visible") // but I got the same results, so I ended up using:
> $(".taskNameItem").remove() // then I checked again:
> $(".Assemble_station") // and now the results are different :)

And all these were done in the console without having to change the code. So you can really learn a lot by putting commands in the console while your code is in a breakpoint. But in jsFiddle, remember to change from the <top frame> to the result frame using the dropdown at the bottom of the console.

The actual problems in your code

The problem with changing overlaps into a jQuery plugin, is that jQuery plugins can be called on many items at the same time. So it would be difficult to adapt it as a plugin to work properly, and you are better off using the original version.

But the problem with using the original function is that it works with normal HTML elements, but your elements are not so simple (because you hidden parts, and the containers have the positions while the contents the have the sizes). So I had to hack into the getPosition function inside overlaps to make it work with your weird HTML:

var overlaps = (function () {
    function getPositions( elem ) {
        var obj = $( elem );
        var pos = obj.position();
        //HACK: weird HTML force me to use its first child's dimensions
        var child = obj.children(":first-child"); 
        var width = child.width();
        var height = child.height();
        return [ [ pos.left, pos.left + width ], [ pos.top, pos.top + height ] ];
    }

Take a look at this new code on how to use the overlaps function (in the second each , I've removed not only the firstobj, but also every other object already tested in previous loops by using i1 + 1 as starting point):

var stations = $('.Assemble_station');
stations.each(function(i1, firstobj) {
    stations.slice(i1 + 1).each(function(i2, secondobj) {
        if(overlaps(firstobj, secondobj)) {
            var obj1 = $(firstobj);
            var obj2 = $(secondobj);
            var objToMove = obj1.position().left >= obj2.position().left ? obj1 : obj2;
            var newTop = objToMove.position().top + 18;
            objToMove.css("top", newTop + 'px');
        }
    });
});

Your other problem is that several elements on your page are sharing ID s. If you give an element an id, it should be the only element with that id in the whole page. jQuery won't work as expected if you don't comply with this basic HTML assumption. I fixed this by removing (instead of hiding) the titles and the yellow bar (and doing it before getting the objects by id), so they won't interfere with the collision detection.

The full solution

You can play with my jsFiddle here: http://jsfiddle.net/protron/NxWxU/8/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM