How to determine if one control overlaps the other?

J

Jay

Hi all,

I know how to find a controls' position obviously (i.e.style left,
right, top, offset, etc.), but what I'm a little stumped on is, if
given two controls' positions, how can I tell if one is overlapping/
invading the space of the other?

For example, I have an AJAX dragpanel and am experiencing the common
'bleed through' of dropdown controls when I drag the panel over them.
Naturally the customer doesn't like this. I experimented a little with
the IFrame solution, but did not have much luck. It seems easier now
to just use the 'ondragend' event and show/hide dropdowns accordingly.

Does anyone have a piece of code where, given two control objects as
passing parameters, it returns true or false in regards to them
overlapping or not?

THANK YOU...
 
D

David Mark

Hi all,

I know how to find a controls' position obviously (i.e.style left,
right, top, offset, etc.), but what I'm a

Do you? The style properties are worthless for that. As for "offset,
etc.", that's a start.

little stumped on is, if
given two controls' positions, how can I tell if one is overlapping/
invading the space of the other?

If you can indeed determine their absolute positions in the document,
you only need their offsetHeight/Width to calculate if they overlap.
Think about it.
For example, I have an AJAX dragpanel and am experiencing the common
'bleed through' of dropdown controls when I drag the panel over them.

That's because you didn't hide the inputs when the drag operation
started.
Naturally the customer doesn't like this. I experimented a little with
the IFrame solution, but did not have much luck. It seems easier now

That Iframe "solution" is not a solution (it is an ugly workaround.)
to just use the 'ondragend' event and show/hide dropdowns accordingly.

There you go. You will need an "ondragstart" event/callback as well.
I assume your widget supports such a thing.
Does anyone have a piece of code where, given two control objects as
passing parameters, it returns true or false in regards to them
overlapping or not?

What library are you using? Presumably it has such a function if it
has drag and drop functionality.
 
T

Thomas 'PointedEars' Lahn

Jay said:
I know how to find a controls' position obviously (i.e.style left,
right, top, offset, etc.), but what I'm a little stumped on is, if
given two controls' positions, how can I tell if one is overlapping/
invading the space of the other?

Compare the coordinates of the corners of one element against the
coordinates of the corresponding corners of the other one.


PointedEars
 
R

RobG

I don't see what AJAX has to do with this, but anyhow...
That's because you didn't hide the inputs when the drag operation
started.

Inputs? I think you mean select elements. Hiding them to stop them
"showing through" is pretty ugly from a users' perspective.

That Iframe "solution" is not a solution (it is an ugly workaround.)

Maybe, but it is a much better solution than toggling their
visibility.


[...]
There is no need to determine if they overlap - cover all of them with
iFrames. You can create all the iFrames at any time before dragging
starts, you might be able to put them in the source HTML but likely
script is better, then just toggle their display property (use a class
and CSS) when dragging starts and again when it ends. If the iFrames
have no visible style, they're invisible, the user will never know
you've done it.

During testing/debugging, give the iFrames a background colour to help
with making sure they're in the right spot.
 
D

David Mark

I don't see what AJAX has to do with this, but anyhow...



Inputs? I think you mean select elements. Hiding them to stop them
"showing through" is pretty ugly from a users' perspective.

I meant inputs. A select element is an input. It isn't an input
element per se, but other input elements bleed through as well. They
all create child windows. And I don't mean JS window objects but
Windows child windows.
Maybe, but it is a much better solution than toggling their
visibility.

Hardly. Creating a bunch of non-standard "dummy" elements and then
going through all of the mess of positioning them is not a better
solution than simply hiding the inputs during the drag operation.
Clearly the inputs are not drop targets, so there is no reason they
need to be visible while dragging.
[...]



There is no need to determine if they overlap - cover all of them with
iFrames. You can create all the iFrames at any time before dragging
starts, you might be able to put them in the source HTML but likely

That would mess up the semantics of the page.
script is better, then just toggle their display property (use a class

That is assuming you can append them and actually adjust their display
property after load.
and CSS) when dragging starts and again when it ends. If the iFrames
have no visible style, they're invisible, the user will never know
you've done it.

Unless they are using an agent that can't handle this convoluted
operation (or IFrames in general.)
During testing/debugging, give the iFrames a background colour to help
with making sure they're in the right spot.

And if they are not, you've got a lot of work ahead. Change a style
sheet in the future and you run the risk of breaking the positioning.
Adding or removing an HTML (or body) border is often good for that.

Trust me. Hiding the inputs is a much simpler, robust and compatible
solution.
 
R

RobG

Hardly. Creating a bunch of non-standard "dummy" elements and then
going through all of the mess of positioning them

That can be done in a few lines of code with a reasonable position
function. The one at Javascript Toolbox seems to do the job OK.

is not a better
solution than simply hiding the inputs during the drag operation.
Clearly the inputs are not drop targets, so there is no reason they
need to be visible while dragging.

Yeah, a bit of playing shows IE makes life tough. I normally only use
iFrames under other elements, I'd forgotten that you can't make them
pretty in IE.

How about a single iFrame under the drag object that moves with it?
Then there's no need to find and hide the selects - I just hate the
idea the selects flashing on and off.
 
D

David Mark

That can be done in a few lines of code with a reasonable position
function. The one at Javascript Toolbox seems to do the job OK.

That is an oversimplification. Even if you just consider the major
browsers in standards mode, there are many quirks and bugs to deal
with.

I looked at the one in JavaScript Toolbox and it is inadequate.
There's not a single feature test, though there is one browser sniff
(an inference from the opera object.) Despite this, borders anywhere
along the way will break this in the latest version of Opera. As for
"OK" positioning, if it is off by a even single pixel it is worthless
for the purpose of covering elements.

Change your style sheet in the future and all previous testing goes
out the window. The easiest way to break these sorts of scripts is to
add borders. There are quirks for HTML borders (and margins), body
borders, scrolling elements with borders and various combinations of
nested positioning.
Yeah, a bit of playing shows IE makes life tough. I normally only use
iFrames under other elements, I'd forgotten that you can't make them
pretty in IE.

I don't follow as I haven't messed with IFrames in a long time. What
do you mean by "pretty."
How about a single iFrame under the drag object that moves with it?

That is a better idea, but still too complicated. You still have to
append an IFrame to the DOM, which is a deal-breaker as far as I am
concerned. Then you have to ensure that it is the same size as the
drag object. If your drag object has borders or padding, you have to
deal with box model issues. If not, who is to say that somebody won't
change the style of it in the future?
Then there's no need to find and hide the selects - I just hate the
idea the selects flashing on and off.

I don't particularly like it either, but it is an imperfect world.
And as for finding and hiding selects, that is a trivial script. Done
right it will work in any browser that supports basic CSS.
 
R

RobG

David said:
That is an oversimplification. Even if you just consider the major
browsers in standards mode, there are many quirks and bugs to deal
with.

I looked at the one in JavaScript Toolbox and it is inadequate.
There's not a single feature test, though there is one browser sniff
(an inference from the opera object.)

I posted the link as an example, I'm not saying it's a perfect library -
there isn't one. But Matt's is as good at what it does as any other
I've stumbled across, and much better than most.

Despite this, borders anywhere
along the way will break this in the latest version of Opera. As for
"OK" positioning, if it is off by a even single pixel it is worthless
for the purpose of covering elements.

You will not find a position library, anywhere, that works for every
browser and every situation (even if "every" is browsers since IE/NN 4).
It only needs to work to the extent that a drag library does, and that
is likely even more limited.

A drag library is probably more dependent on accurate positioning than
the suggested select hiding script.

Change your style sheet in the future and all previous testing goes
out the window. The easiest way to break these sorts of scripts is to
add borders. There are quirks for HTML borders (and margins), body
borders, scrolling elements with borders and various combinations of
nested positioning.

Which will affect the drag library too. It should probably use the same
position functions as whatever is used to place the iFrames. I've
already agreed that my original solution is a poor one, so this is all
theoretical now.

I don't follow as I haven't messed with IFrames in a long time. What
do you mean by "pretty."

It takes a bit of messing around to get rid of the borders.

<URL:
http://forums.devshed.com/css-help-116/iframe-border-problems-css-ie-122093.html
That is a better idea, but still too complicated.

Too complicated to keep two objects, both controlled by the same script,
the same size and position? If you can't do it with two, you can't do
it with one either - in which case there's no need for the second. :)

You still have to
append an IFrame to the DOM, which is a deal-breaker as far as I am
concerned.

We are talking about dragging DOM objects around and repositioning them
on the page (and maybe within the DOM), I think it's a bit coy to say
you can't handle adding a single extra element temporarily to the DOM.

Then you have to ensure that it is the same size as the
drag object.

The entire page is at your command, you aren't trying to drag some
random object in a totally unknown environment. If you are going to try
and write a drag library that works in every browser for every possible
situation, it *will* fail in places. I think everyone who writes such
libraries accepts that.

If your drag object has borders or padding, you have to
deal with box model issues. If not, who is to say that somebody won't
change the style of it in the future?

That is a QC issue common to every bit of code every written, it is not
exclusive to web page authoring.

There are a lot of scripts being written that are utterly dependent on a
precise DOM order, mostly encouraged by script libraries that encourage
walking the DOM with functions like 'up', 'next' and 'previous'. Insert
a single extra element into those and see what happens.

I don't particularly like it either, but it is an imperfect world.
And as for finding and hiding selects, that is a trivial script. Done
right it will work in any browser that supports basic CSS.

But not all browsers do, though likely more support CSS than the drag
and drop stuff the OP is attempting to implement.
 
D

David Mark

David said:
[...]
Creating a bunch of non-standard "dummy" elements and then
going through all of the mess of positioning them
That can be done in a few lines of code with a reasonable position
function. The one at Javascript Toolbox seems to do the job OK.
That is an oversimplification. Even if you just consider the major
browsers in standards mode, there are many quirks and bugs to deal
with.
I looked at the one in JavaScript Toolbox and it is inadequate.
There's not a single feature test, though there is one browser sniff
(an inference from the opera object.)

I posted the link as an example, I'm not saying it's a perfect library -
there isn't one. But Matt's is as good at what it does as any other
I've stumbled across, and much better than most.

I agree that most positioning snippets are useless, but didn't see
that one as much better.
You will not find a position library, anywhere, that works for every
browser and every situation (even if "every" is browsers since IE/NN 4).

The script I use works for virtually everything that matters, though I
certainly haven't tested with NN 4 (which doesn't matter.) My point
is that the one posted won't even work properly in the latest version
of Opera in standards mode.
It only needs to work to the extent that a drag library does, and that
is likely even more limited.

How so?
A drag library is probably more dependent on accurate positioning than
the suggested select hiding script.

The drop portion of the lib has to do the same thing (find the
absolute position of an element.)
Which will affect the drag library too. It should probably use the same

That depends on how it stacks up to the posted positioning script. If
it has the same limitations then it will break.
position functions as whatever is used to place the iFrames. I've
already agreed that my original solution is a poor one, so this is all
theoretical now.



It takes a bit of messing around to get rid of the borders.

<URL:http://forums.devshed.com/css-help-116/iframe-border-problems-css-ie-...


Too complicated to keep two objects, both controlled by the same script,
the same size and position? If you can't do it with two, you can't do
it with one either - in which case there's no need for the second. :)

I don't follow you there. My point is that it is easy to break with
style changes. Introducing script to handle this situation makes for
a more complicated solution.
We are talking about dragging DOM objects around and repositioning them
on the page (and maybe within the DOM), I think it's a bit coy to say
you can't handle adding a single extra element temporarily to the DOM.

My problem is with adding, positioning and sizing a non-standard
IFrame to the DOM as a workaround when you could just set the
visibility style of the form elements.
The entire page is at your command, you aren't trying to drag some

Until it is passed on to another person to maintain. If the next
owner adds a border to the drag panel or HTML or whatever, they will
likely break the workaround. I am not saying it is impossible to make
the script(s) robust enough to handle such a change, but that it is a
lot more work than hiding elements.
random object in a totally unknown environment. If you are going to try
and write a drag library that works in every browser for every possible
situation, it *will* fail in places. I think everyone who writes such
libraries accepts that.

The drag part shouldn't fail, even in IE4. The drop part needs to use
robust positioning code if it is to work in even the latest versions
of major browsers in standards mode. Most positioning snippets on the
Web are inadequate for this.
That is a QC issue common to every bit of code every written, it is not
exclusive to web page authoring.

My point is that positioning code is complex and susceptible to minor
CSS changes.
There are a lot of scripts being written that are utterly dependent on a
precise DOM order, mostly encouraged by script libraries that encourage
walking the DOM with functions like 'up', 'next' and 'previous'. Insert
a single extra element into those and see what happens.

Lots of people write and post bad scripts. I wouldn't use or
recommend them. In the case at hand, I disagree with the
recommendation to use a script that is easy to break in favor of a few
lines of code that will never break.
But not all browsers do, though likely more support CSS than the drag
and drop stuff the OP is attempting to implement.

The browsers that do not support CSS will not support drag and drop.
If you can't drag the panel, you don't need to hide the form
elements. The drag lib the OP is using probably doesn't take this
into account, so you would need to test for CSS support in your hiding
code.

if (el.style) { el.style.visibility = 'hidden'; }

If I were using a third-party drag script, I would do something like
this before passing the panel to it.

if (el.style && typeof(el.style.position) == 'string') ...

If that fails, drag and drop is not initialized and the hiding code
will never called.
 
J

Jay

Geez. I never thought this would have spurred such a heated debate.
Regardless, I almost have it working the way I want it. It works for
the most part, but when frames or nested levels come into play, the
top and/or bottom coordinates become incorrect - somehow it's not
getting all of the height and the test is failing.

I should hopefully have this corrected soon. I share code where I come
from, so here ya go...

HTML TAG ...ondragstart="ShowDropDownsAgain();"
ondragend="HideDropDownsInWay(this);"...HTML TAG

function HideDropDownsInWay(ctrl1)
{
var L1, R1, Top1, Bot1;
var L2, R2, Top2, Bot2;
var ctrls;
var ctrl2;

L1 = elementLeft(ctrl1);
R1 = elementRight(ctrl1);
Top1 = elementTop(ctrl1);
Bot1 = elementBottom(ctrl1);

ctrls = document.getElementsByTagName("SELECT");
for(var i=0;i<ctrls.length;i++)
{
var L2 = elementLeft(ctrls);
var R2 = elementRight(ctrls);
var Top2 = elementTop(ctrls);
var Bot2 = elementBottom(ctrls);

if(
(Top1>Bot2) ||
(L1>R2) ||
(R1<L2) ||
(Bot1<Top2)
)
ctrls.style.display = 'inline';
else
ctrls.style.display = 'none';
}
}
function elementTop(eSrc)
{
var iTop = 0;
var eParent;
eParent = eSrc;
while (eParent.tagName.toUpperCase() != "BODY")
{
iTop += eParent.offsetTop;
eParent = eParent.offsetParent;
}
return iTop;
}
function elementBottom(eSrc)
{
var iTop = 0;
var eParent;
eParent = eSrc;
while (eParent.tagName.toUpperCase() != "BODY")
{
iTop += eParent.offsetTop;
eParent = eParent.offsetParent;
}
return iTop+eSrc.offsetHeight;//really the bottom position...
}
function elementLeft(eSrc)
{
var iLeft = 0;
var eParent;
eParent = eSrc;
while (eParent.tagName.toUpperCase() != "BODY")
{
iLeft += eParent.offsetLeft;
eParent = eParent.offsetParent;
}
return iLeft;
}
function elementRight(eSrc)
{
var iLeft = 0;
var eParent;
eParent = eSrc;
while (eParent.tagName.toUpperCase() != "BODY")
{
iLeft += eParent.offsetLeft;
eParent = eParent.offsetParent;
}
return iLeft + eSrc.offsetWidth;//really the right position...
}
function ShowDropDownsAgain()
{
ctrls = document.getElementsByTagName("SELECT");
for(var i=0;i<ctrls.length;i++)
ctrls.style.display = 'inline';
}
 
D

David Mark

Geez. I never thought this would have spurred such a heated debate.
Regardless, I almost have it working the way I want it. It works for
the most part, but when frames or nested levels come into play, the

What do frames have to do with this? By nested levels, do you mean
nested elements?
top and/or bottom coordinates become incorrect - somehow it's not
getting all of the height and the test is failing.

As I mentioned previously, it isn't easy to make work across all
browsers.
I should hopefully have this corrected soon. I share code where I come
from, so here ya go...

It seems to me that you just need to hide the selects while dragging
and show them again when the drag ends. The drag and drop script
should be able to constrain the movements of the panel to a relatively
positioned container that is free of selects. If you really need to
allow the panel to be dragged all over the page, you can will need to
calculate an absolutely positioned elements' position relative to
several static elements. As you have found out, this is not as simple
as it sounds. I can tell you from experience that there are several
feature tests required to make it work perfectly across just the major
browsers. They involve creating a dummy element when the DOM content
is ready, appending it to the body, comparing computed style rules to
expected results and setting flags accordingly. In other words, there
is no quickie solution.
HTML TAG ...ondragstart="ShowDropDownsAgain();"
ondragend="HideDropDownsInWay(this);"...HTML TAG

Is this an IE-only app? I thought you were using some library for
drag and drop. Does this lib interpret these event attributes?

Also, if this is meant for IE-only, you are in luck as you can use
document.body.getBoundingClientRect. My positioning code uses that
when detected. Gecko browsers have a similar method
(document.getBoxObjectFor), but it is a little more work to keep in
line. The offsetParent loop is always the last resort fallback as it
is the most problematic approach.
function HideDropDownsInWay(ctrl1)
{
var L1, R1, Top1, Bot1;
var L2, R2, Top2, Bot2;
var ctrls;
var ctrl2;

L1 = elementLeft(ctrl1);
R1 = elementRight(ctrl1);
Top1 = elementTop(ctrl1);
Bot1 = elementBottom(ctrl1);

ctrls = document.getElementsByTagName("SELECT");
for(var i=0;i<ctrls.length;i++)
{
var L2 = elementLeft(ctrls);
var R2 = elementRight(ctrls);
var Top2 = elementTop(ctrls);
var Bot2 = elementBottom(ctrls);

if(
(Top1>Bot2) ||
(L1>R2) ||
(R1<L2) ||
(Bot1<Top2)
)
ctrls.style.display = 'inline';
else
ctrls.style.display = 'none';
}}

function elementTop(eSrc)
{
var iTop = 0;
var eParent;
eParent = eSrc;
while (eParent.tagName.toUpperCase() != "BODY")


There's a problem (or several) right there. You didn't test if
eParent exists. You are using tagName, instead of comparing eParent
to the body element. And of course, the offset doesn't always stop at
the body for static elements.
{
iTop += eParent.offsetTop;

Why are you trying to re-invent the wheel? The previously posted
example, though inadequate for general purpose use, was further along
than these initial efforts. The appearance that you "almost got it
working" in whatever browser you tested with is an illusion. See what
happens when you add borders to nested elements. Then fix it in most
browsers by adding clientTop, then try it in Opera 9 and see that
you've accounted for the border twice. That's feature test #1.

Post a working example of your app so I can see what it is trying to
do with this drag panel and the selects. I'm sure there is an easier
solution than what you are trying to do here.
 
J

Jay

OK OK man. You got to cut me some slack here because I don't have all
the time in the world than you apparently do.
As I mentioned previously, it isn't easy to make work across all
browsers.

I'm not interested in all browsers. Just IE.
It seems to me that you just need to hide the selects while dragging
and show them again when the drag ends.

I prefer to show/hide when you drop.
Is this an IE-only app?
YES

I thought you were using some library for
drag and drop.
NO

Also, if this is meant for IE-only, you are in luck as you can use
document.body.getBoundingClientRect. My positioning code uses that
when detected.

So share your code then instead of talking about it.
Why are you trying to re-invent the wheel?

Because no one has been so kind as me to share code.
The previously posted
example, though inadequate for general purpose use, was further along
than these initial efforts.

I don't see any previously posted example. Care to SHARE?
 
D

David Mark

OK OK man. You got to cut me some slack here because I don't have all
the time in the world than you apparently do.

You really don't help yourself do you? If you don't have time to
write your own code, then that is your own problem.
I'm not interested in all browsers. Just IE.




I prefer to show/hide when you drop.


YES

Stop shouting.

Shouting again. If you wrote your own drag and drop code, then you
should be able to hide form elements.
So share your code then instead of talking about it.

I've got a better idea. Why don't you search MSDN for
"getBoundingClientRect."
Because no one has been so kind as me to share code.

Somebody did earlier in the thread. Or rather they cited a well-known
example that should be very easy to find with Google.
 
J

Jay

I was shouting because you are extremely annoying.

I got it working. Thanks no to you and your snide attitude.

I was trying to be nice and you rudely swiped back at me every time.
Do me a favor and go help someone else. I'm interested in code and
solving problems. Not arguing with babies.
 
D

David Mark

I was shouting because you are extremely annoying.

I got it working. Thanks no to you and your snide attitude.

I was trying to be nice and you rudely swiped back at me every time.

No, you were trying to get me to write your code for you.
Do me a favor and go help someone else. I'm interested in code and

I've done enough favors for you. If you don't like the advice given
here, feel free to find another "help desk."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top