Wow. That is some serious abuse of for-loops.
It does seem to mostly work. I have translated
it into more readable code and I will post it here
for future reference.
I am not sure I understand exactly what's going on,
but I think if obj2 (in my translated code) is a single
object, it's converted into a single-element array.
Otherwise, if the user passed an array of objects,
hitTest() detect collisions with all the elements in
that array. I have tried sending the function an
array of objects but I couldn't get it to work.
hitTest = function(obj1, obj2){
function getOffset(obj){
var objBounds = {
objLeft: obj.offsetLeft,
objTop: obj.offsetTop,
objRight: obj.offsetWidth,
objBottom: obj.offsetHeight
};
for( ; obj = obj.offsetParent; )
{
objBounds.objLeft += obj.offsetLeft;
objBounds.objTop += obj.offsetTop;
}
objBounds.objRight += objBounds.objLeft
objBounds.objBottom += objBounds.objTop
return objBounds;
}
var obj2Bounds
var collisionArray = [];
var obj1Bounds = getOffset(obj1);
// My guess:
// If obj2 is a single object, convert it to a single
// element array. Now that obj2 is definitely an
// array, set i to the length of that array
var j = isNaN(obj2.length);
var i = (j ? obj2 = [obj2] : obj2).length
for(; i; )
{
obj2Bounds = getOffset(obj2[--i])
if ( (obj1Bounds.objLeft == obj2Bounds.objLeft ||
(obj1Bounds.objLeft > obj2Bounds.objLeft ?
obj1Bounds.objLeft <= obj2Bounds.objRight :
obj2Bounds.objLeft <= obj1Bounds.objRight))
&& (obj1Bounds.objTop == obj2Bounds.objTop ||
(obj1Bounds.objTop > obj2Bounds.objTop ?
obj1Bounds.objTop <= obj2Bounds.objBottom :
obj2Bounds.objTop <= obj1Bounds.objBottom)))
{
collisionArray[collisionArray.length] = obj2
;
}
}
// My guess:
// if obj2 is a single object and it collides with obj1,
// collisionArray.length == 1 so !!collisionArray.length == true
// if obj2 is an array of objects, return an array of
// the subset of obj2 objects with which obj1 collidess
return j ? !!collisionArray.length : collisionArray;
};
Thanks for your post, you saved me a lot of pain.
You know, I was working on this very thing a couple weeks ago to
implement classic drag and drop. Luckily for you I have explored this
issue extensively and can save you hours of researching by telling you
what I found out.
The short of it all, you can't. Both IE and FF just don't allow it
right now. What you do need is a collusion function which will tell you
when one item (the item you are dragging) has collided (is over)
another element. When the two elements collide, you can call a function
which will give you the same effect as mouseover on the second element.
I got this off a guy here on the forums, and even though it is a bit
unreadable, it works like a charm and allows me to do the drag and drop
I need.
hitTest = function(o, l){
function getOffset(o){
for(var r = {l: o.offsetLeft, t: o.offsetTop, r: o.offsetWidth,
b: o.offsetHeight};
o = o.offsetParent; r.l += o.offsetLeft, r.t +=
o.offsetTop);
return r.r += r.l, r.b += r.t, r;
}
for(var b, s, r = [], a = getOffset(o), j = isNaN(l.length), i = (j
? l = [l] : l).length; i;
b = getOffset(l[--i]), (a.l == b.l || (a.l > b.l ? a.l <= b.r :
b.l <= a.r))
&& (a.t == b.t || (a.t > b.t ? a.t <= b.b : b.t <= a.b)) &&
(r[r.length] = l
));
return j ? !!r.length : r;
};
Use: hitTest(obj1,obj2)
Description: Returns true and false if the reference to obj1 and obj2
overlap or "collided".
You would put this in your mousemove event within an if statement. If
it is true, call the function you want to call as if it was in a
mouseover of the second element.
Good luck!