Onscreen Element Position 
Author Message
 Onscreen Element Position

I would like to create an HTC control similar to a select box (DropDownList)
that offers the user a chance to open the box and make a single selection
from the drop down list. I would also like the HTC to be flexible and be
placed anywhere in the document or even nested in a absolutely positioned
element. My primary motivation to create this control is the "Shine-Through"
issue that causes the standard select elements to "Shine-Through" other
absolutely positioned elements (even with a greater zIndex).

How do determine the position of the base element onscreen inorder to
properly place the drop down list box?

I have tried recursion from the source element back to the document.body,
summing up the offsetTop and offsetLeft properties along the way (and
ignoring the redundant ones like tr and tbody) but that doesn't work well in
all cases.

I have also tried using the clientX and Y coordinates for the onclick and
use the offset of the event to find my way back to the element's absolute
position. This works well but I would also like the element to participate
in the tab sequence and open using the onkeydown and onkeypress events,
which render mouse clientX and Y's of wherever the mouse is currently (which
doesn't help).

Does anyone know a good way of finding an elements true offsetTop and
offsetLeft to the corner of the current frame/window?

Thanks in advance,

Justin Foster



Mon, 27 Jun 2005 02:51:31 GMT  
 Onscreen Element Position

I believe I might have found my own answer:

var offsetLeft = 0;
var offsetTop = 0
var currentElement = elementYouWantToFindLocationOf;
while(currentElement!=window.document.body) {
    offsetTop += currentElement.offsetTop;
    offsetLeft += currentElement.offsetLeft;
    offsetTop -= currentElement.scrollTop;
    offsetLeft -= currentElement.scrollLeft;
    currentElement = currentElement.offsetParent;

Quote:
}



Quote:
> I would like to create an HTC control similar to a select box
(DropDownList)
> that offers the user a chance to open the box and make a single selection
> from the drop down list. I would also like the HTC to be flexible and be
> placed anywhere in the document or even nested in a absolutely positioned
> element. My primary motivation to create this control is the
"Shine-Through"
> issue that causes the standard select elements to "Shine-Through" other
> absolutely positioned elements (even with a greater zIndex).

> How do determine the position of the base element onscreen inorder to
> properly place the drop down list box?

> I have tried recursion from the source element back to the document.body,
> summing up the offsetTop and offsetLeft properties along the way (and
> ignoring the redundant ones like tr and tbody) but that doesn't work well
in
> all cases.

> I have also tried using the clientX and Y coordinates for the onclick and
> use the offset of the event to find my way back to the element's absolute
> position. This works well but I would also like the element to participate
> in the tab sequence and open using the onkeydown and onkeypress events,
> which render mouse clientX and Y's of wherever the mouse is currently
(which
> doesn't help).

> Does anyone know a good way of finding an elements true offsetTop and
> offsetLeft to the corner of the current frame/window?

> Thanks in advance,

> Justin Foster



Mon, 27 Jun 2005 03:51:34 GMT  
 Onscreen Element Position

if you're really wanting to approximate the select control, you'll certainly
want to use the popup object for the drop-down menu, because the drop-down
menu of a select can draw beyond the window border.

when you do this, all you'll have to do is provide the offsetHeight of the
base element as the y-position, zero as the x, (width and height), and the
base element as the 5th param (which tells the popup which element in the
document the x and y you provided are relative to) to the show() method.

if you do not want to use the popup, all you have to do to get the absolute
position of the base element is recurse through the offset parents of the
element, summing the offsetLeft and offsetTop values, until the offset
parent is undefined.

it was a challenging control to make, but much more rewarding than many of
the hacks i've seen.  the most difficult (or least elegant) thing about it
was getting the events from the popup window to the main window.  there were
lots of pitfalls, but the only problem i still have in the popup version is
that i haven't been able successfully drag select (from the base element to
the menu) an element in the list.  for some reason, the mouseup event just
doesn't happen in either the popup window or the main window.  this isn't a
problem with absolutely positioned divs.  creating the control with the div
just limits you to the boundaries of the screen and potential z-index
conflicts (which is the main reason i used the popup version).

you can create a cross-browser compatible control, but i wouldn't guess
you'd be posting to this group for that info.  in that case, a "similar"
control is the best you can do.

- ian


Quote:
> I would like to create an HTC control similar to a select box
(DropDownList)
> that offers the user a chance to open the box and make a single selection
> from the drop down list. I would also like the HTC to be flexible and be
> placed anywhere in the document or even nested in a absolutely positioned
> element. My primary motivation to create this control is the
"Shine-Through"
> issue that causes the standard select elements to "Shine-Through" other
> absolutely positioned elements (even with a greater zIndex).

> How do determine the position of the base element onscreen inorder to
> properly place the drop down list box?

> I have tried recursion from the source element back to the document.body,
> summing up the offsetTop and offsetLeft properties along the way (and
> ignoring the redundant ones like tr and tbody) but that doesn't work well
in
> all cases.

> I have also tried using the clientX and Y coordinates for the onclick and
> use the offset of the event to find my way back to the element's absolute
> position. This works well but I would also like the element to participate
> in the tab sequence and open using the onkeydown and onkeypress events,
> which render mouse clientX and Y's of wherever the mouse is currently
(which
> doesn't help).

> Does anyone know a good way of finding an elements true offsetTop and
> offsetLeft to the corner of the current frame/window?

> Thanks in advance,

> Justin Foster



Mon, 27 Jun 2005 04:50:33 GMT  
 Onscreen Element Position

Thanks Ian,

That was helpful. I had not considered using the popup.

I actually went with a recursion like this:

var offsetLeft = 0;
var offsetTop = 0
var currentElement = elementYouWantToFindLocationOf;
while(currentElement!=window.document.body) {
    offsetTop += currentElement.offsetTop;
    offsetLeft += currentElement.offsetLeft;
    offsetTop -= currentElement.scrollTop;
    offsetLeft -= currentElement.scrollLeft;
    currentElement = currentElement.offsetParent;

Quote:
}

and it seams to work fine. As for going outside the boundries of the window,
I am currently flipping the opening access when the list is too large.

I will consider trying the popup to see if it works as well.

For your select control did you create it as a HTC or inline script? I
created my HTC as a behavior for all selects in the global style sheet like:

SELECT {
    display: none;
    behavior: url(..);

Quote:
}

In the HTC I appended my select after the hidden select  that has the
behavior (Using element.insertAdjacentElement('afterEnd',mySelect);)  and I
used onPropertyChange to notify my of index changes. In turn, my control
fired back the changes to the real select (Changing the selected index).
This allows other developers to use the standard select and program it
client side or have it post back without changing a thing and still fixing
the "Shine-Through" problem.

Thanks again,
Justin Foster


Quote:
> if you're really wanting to approximate the select control, you'll
certainly
> want to use the popup object for the drop-down menu, because the drop-down
> menu of a select can draw beyond the window border.

> when you do this, all you'll have to do is provide the offsetHeight of the
> base element as the y-position, zero as the x, (width and height), and the
> base element as the 5th param (which tells the popup which element in the
> document the x and y you provided are relative to) to the show() method.

> if you do not want to use the popup, all you have to do to get the
absolute
> position of the base element is recurse through the offset parents of the
> element, summing the offsetLeft and offsetTop values, until the offset
> parent is undefined.

> it was a challenging control to make, but much more rewarding than many of
> the hacks i've seen.  the most difficult (or least elegant) thing about it
> was getting the events from the popup window to the main window.  there
were
> lots of pitfalls, but the only problem i still have in the popup version
is
> that i haven't been able successfully drag select (from the base element
to
> the menu) an element in the list.  for some reason, the mouseup event just
> doesn't happen in either the popup window or the main window.  this isn't
a
> problem with absolutely positioned divs.  creating the control with the
div
> just limits you to the boundaries of the screen and potential z-index
> conflicts (which is the main reason i used the popup version).

> you can create a cross-browser compatible control, but i wouldn't guess
> you'd be posting to this group for that info.  in that case, a "similar"
> control is the best you can do.

> - ian



> > I would like to create an HTC control similar to a select box
> (DropDownList)
> > that offers the user a chance to open the box and make a single
selection
> > from the drop down list. I would also like the HTC to be flexible and be
> > placed anywhere in the document or even nested in a absolutely
positioned
> > element. My primary motivation to create this control is the
> "Shine-Through"
> > issue that causes the standard select elements to "Shine-Through" other
> > absolutely positioned elements (even with a greater zIndex).

> > How do determine the position of the base element onscreen inorder to
> > properly place the drop down list box?

> > I have tried recursion from the source element back to the
document.body,
> > summing up the offsetTop and offsetLeft properties along the way (and
> > ignoring the redundant ones like tr and tbody) but that doesn't work
well
> in
> > all cases.

> > I have also tried using the clientX and Y coordinates for the onclick
and
> > use the offset of the event to find my way back to the element's
absolute
> > position. This works well but I would also like the element to
participate
> > in the tab sequence and open using the onkeydown and onkeypress events,
> > which render mouse clientX and Y's of wherever the mouse is currently
> (which
> > doesn't help).

> > Does anyone know a good way of finding an elements true offsetTop and
> > offsetLeft to the corner of the current frame/window?

> > Thanks in advance,

> > Justin Foster



Mon, 27 Jun 2005 05:04:29 GMT  
 Onscreen Element Position
your solution is pretty close to what i have except i exit the loop when the
offsetParent == undefined.  i return the point set like:

return { x : x, y : y};

as for inline vs. HTC, i did both - i generally start with the HTML that i
will need and applying a JScript class to it.  once i get this working to
satisfaction, i create an HTC that creates the HTML from the custom tag spec
and then instantiates the object.  this is really nice in that it can
handle/fire events in the same way that a native element does.

this is also nice for inheritance.  while you can't extend a behavior (as
far as i know) you can extend the class it is based on via prototype
inheritance and create a new behavior that encapsulates its implementation.
i've done this for a combo-box that extended my custom select control and a
couple other specialized tables, menus and toolbar items.

i do NOT recommend using attached behaviors.  element behaviors "behave"
much better, since they are synchronously bound.

your solution is pretty cool in how you allow the author to write a standard
select, but actually render your own control.  i inserted a hidden input
into the custom tag and assign it the name i gave the custom tag, and update
its value based on events in my object, so form submits still get the value.
i like how element behaviors are first class elements in the document
hierarchy and they make authoring much simpler.  it can be difficult for
someone else to maintain code with attached behaviors since what you see,
isn't exactly what you get. whereas it is clear that a custom tag is going
to have a different behavior.

cheers,
ian


Quote:
> Thanks Ian,

> That was helpful. I had not considered using the popup.

> I actually went with a recursion like this:

> var offsetLeft = 0;
> var offsetTop = 0
> var currentElement = elementYouWantToFindLocationOf;
> while(currentElement!=window.document.body) {
>     offsetTop += currentElement.offsetTop;
>     offsetLeft += currentElement.offsetLeft;
>     offsetTop -= currentElement.scrollTop;
>     offsetLeft -= currentElement.scrollLeft;
>     currentElement = currentElement.offsetParent;
> }

> and it seams to work fine. As for going outside the boundries of the
window,
> I am currently flipping the opening access when the list is too large.

> I will consider trying the popup to see if it works as well.

> For your select control did you create it as a HTC or inline script? I
> created my HTC as a behavior for all selects in the global style sheet
like:

> SELECT {
>     display: none;
>     behavior: url(..);
> }

> In the HTC I appended my select after the hidden select  that has the
> behavior (Using element.insertAdjacentElement('afterEnd',mySelect);)  and
I
> used onPropertyChange to notify my of index changes. In turn, my control
> fired back the changes to the real select (Changing the selected index).
> This allows other developers to use the standard select and program it
> client side or have it post back without changing a thing and still fixing
> the "Shine-Through" problem.

> Thanks again,
> Justin Foster



> > if you're really wanting to approximate the select control, you'll
> certainly
> > want to use the popup object for the drop-down menu, because the
drop-down
> > menu of a select can draw beyond the window border.

> > when you do this, all you'll have to do is provide the offsetHeight of
the
> > base element as the y-position, zero as the x, (width and height), and
the
> > base element as the 5th param (which tells the popup which element in
the
> > document the x and y you provided are relative to) to the show() method.

> > if you do not want to use the popup, all you have to do to get the
> absolute
> > position of the base element is recurse through the offset parents of th
e
> > element, summing the offsetLeft and offsetTop values, until the offset
> > parent is undefined.

> > it was a challenging control to make, but much more rewarding than many
of
> > the hacks i've seen.  the most difficult (or least elegant) thing about
it
> > was getting the events from the popup window to the main window.  there
> were
> > lots of pitfalls, but the only problem i still have in the popup version
> is
> > that i haven't been able successfully drag select (from the base element
> to
> > the menu) an element in the list.  for some reason, the mouseup event
just
> > doesn't happen in either the popup window or the main window.  this
isn't
> a
> > problem with absolutely positioned divs.  creating the control with the
> div
> > just limits you to the boundaries of the screen and potential z-index
> > conflicts (which is the main reason i used the popup version).

> > you can create a cross-browser compatible control, but i wouldn't guess
> > you'd be posting to this group for that info.  in that case, a "similar"
> > control is the best you can do.

> > - ian



> > > I would like to create an HTC control similar to a select box
> > (DropDownList)
> > > that offers the user a chance to open the box and make a single
> selection
> > > from the drop down list. I would also like the HTC to be flexible and
be
> > > placed anywhere in the document or even nested in a absolutely
> positioned
> > > element. My primary motivation to create this control is the
> > "Shine-Through"
> > > issue that causes the standard select elements to "Shine-Through"
other
> > > absolutely positioned elements (even with a greater zIndex).

> > > How do determine the position of the base element onscreen inorder to
> > > properly place the drop down list box?

> > > I have tried recursion from the source element back to the
> document.body,
> > > summing up the offsetTop and offsetLeft properties along the way (and
> > > ignoring the redundant ones like tr and tbody) but that doesn't work
> well
> > in
> > > all cases.

> > > I have also tried using the clientX and Y coordinates for the onclick
> and
> > > use the offset of the event to find my way back to the element's
> absolute
> > > position. This works well but I would also like the element to
> participate
> > > in the tab sequence and open using the onkeydown and onkeypress
events,
> > > which render mouse clientX and Y's of wherever the mouse is currently
> > (which
> > > doesn't help).

> > > Does anyone know a good way of finding an elements true offsetTop and
> > > offsetLeft to the corner of the current frame/window?

> > > Thanks in advance,

> > > Justin Foster



Mon, 27 Jun 2005 07:26:33 GMT  
 Onscreen Element Position
i use the following functions from webreference.com

function DL_GetElementLeft(eElement)
{
   if (!eElement && this)                    // if argument is invalid
   {                                         // (not specified, is null or
is 0)
      eElement = this;                       // and function is a method
   }                                         // identify the element as the
method owner

   var DL_bIE = document.all ? true : false; // initialize var to identify
IE

   var nLeftPos = eElement.offsetLeft;       // initialize var to store
calculations
   var eParElement = eElement.offsetParent;  // identify first offset parent
element

   while (eParElement != null)
   {                                         // move up through element
hierarchy

      if(DL_bIE)                             // if browser is IE, then...
      {
         if( (eParElement.tagName != "TABLE") && (eParElement.tagName !=
"BODY") )
         {                                   // if parent is not a table or
the body, then...
            nLeftPos += eParElement.clientLeft; // append cell border width
to calcs
         }
      }
      else                                   // if browser is Gecko, then...
      {
         if(eParElement.tagName == "TABLE")  // if parent is a table,
then...
         {                                   // get its border as a number
            var nParBorder = parseInt(eParElement.border);
            if(isNaN(nParBorder))            // if no valid border
attribute, then...
            {                                // check the table's frame
attribute
               var nParFrame = eParElement.getAttribute('frame');
               if(nParFrame != null)         // if frame has ANY value,
then...
               {
                  nLeftPos += 1;             // append one pixel to counter
               }
            }
            else if(nParBorder > 0)          // if a border width is
specified, then...
            {
               nLeftPos += nParBorder;       // append the border width to
counter
            }
         }
      }
      nLeftPos += eParElement.offsetLeft;    // append left offset of parent
      eParElement = eParElement.offsetParent; // and move up the element
hierarchy
   }                                         // until no more offset parents
exist
   return nLeftPos;                          // return the number calculated

Quote:
}

function DL_GetElementTop(eElement)
{
   if (!eElement && this)                    // if argument is invalid
   {                                         // (not specified, is null or
is 0)
      eElement = this;                       // and function is a method
   }                                         // identify the element as the
method owner

   var DL_bIE = document.all ? true : false; // initialize var to identify
IE

   var nTopPos = eElement.offsetTop;         // initialize var to store
calculations
   var eParElement = eElement.offsetParent;  // identify first offset parent
element

   while (eParElement != null)
   {                                         // move up through element
hierarchy
      if(DL_bIE)                             // if browser is IE, then...
      {
         if( (eParElement.tagName != "TABLE") && (eParElement.tagName !=
"BODY") )
         {                                   // if parent a table cell,
then...
            nTopPos += eParElement.clientTop; // append cell border width to
calcs
         }
      }
      else                                   // if browser is Gecko, then...
      {
         if(eParElement.tagName == "TABLE")  // if parent is a table,
then...
         {                                   // get its border as a number
            var nParBorder = parseInt(eParElement.border);
            if(isNaN(nParBorder))            // if no valid border
attribute, then...
            {                                // check the table's frame
attribute
               var nParFrame = eParElement.getAttribute('frame');
               if(nParFrame != null)         // if frame has ANY value,
then...
               {
                  nTopPos += 1;              // append one pixel to counter
               }
            }
            else if(nParBorder > 0)          // if a border width is
specified, then...
            {
               nTopPos += nParBorder;        // append the border width to
counter
            }
         }
      }

      nTopPos += eParElement.offsetTop;      // append top offset of parent
      eParElement = eParElement.offsetParent; // and move up the element
hierarchy
   }                                         // until no more offset parents
exist
   return nTopPos;                           // return the number calculated

Quote:
}

etan


Mon, 27 Jun 2005 08:16:39 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. Working out whether a HTML element is actually onscreen

2. DOM and element positioning

3. Forms elements are not displayed in positioned divs

4. Element Positioning

5. Work out the absolute position of an element

6. Finding element positions

7. Height of positioned elements in IE!!!!!!

8. Determining positions of elements

9. Changing the position of HTML elements

10. Cursor position in the TEXTAREA element

11. Find an HTML element at position x,y

12. position of an XML element (XSLT)

 

 
Powered by phpBB® Forum Software