Getting a button's position

Discussion in 'Javascript' started by Ynot, Apr 17, 2009.

  1. Ynot

    Ynot Guest

    I want to simulate a cursor moving across the Web page and pushing a button.
    I wrote some JavaScript functions to move a graphic image. Works fine.
    However, I hard-coded the x and y coordinates where the graphic image starts
    (at a position below the button) and ends (at a position on the button) with
    literal values, which is bad because not everyone uses the same screen
    resolution I'm using.

    I wrote more functions to calculate where to put the graphic image at the
    beginning and where to move it to. Unfortunately, I'm getting an "error on
    page" after I try to use document.getElementById( ) in my code. I've tried
    several alternatives, including calling another function called findPosY( ).
    I'm getting nowhere with that. It gives me "error on page," too.

    Here is the HTML for the button. It's in the body, not inside a form or div
    element.

    <INPUT id=btn type=button value="OK">

    Here's my code (located as a JavaScript script between <head> and </head>),
    along with a few alternatives I've tried and commented out. I can assign
    the document.getElementById('btn') to a variable successfully, but every
    "num =" assignment I tried afterwards using that variable failed. Can
    anyone please point out what I'm doing wrong and explain how to fix it?
    Thanks.

    function getStartPosTop()
    {
    //return 250; // works, but it's hard-coded.

    var num;
    var obj = document.getElementById('btn'); // can't I use this element
    as an object?
    num = obj.style.top + 150; // put the graphic 150 px below the btn
    to push.
    //num = obj.offsetTop + 150;
    //num = obj.style.top;
    //num = obj.offsetTop;
    //num = obj.style.offsetTop;
    //num = findPosY(obj);
    return num;
    }

    function findPosY(obj)
    {
    var curtop = 0;
    if(obj.offsetParent)
    while(1)
    {
    curtop += obj.offsetTop;
    if(!obj.offsetParent)
    break;
    obj = obj.offsetParent;
    }
    else if(obj.y)
    curtop += obj.y;
    return curtop;
    }
     
    Ynot, Apr 17, 2009
    #1
    1. Advertising

  2. Ynot

    Sister Ray Guest

    On Apr 17, 3:31 am, "Ynot" <> wrote:

    >    var num;
    >    var obj = document.getElementById('btn');    // can't I use this element
    > as an object?
    >    num = obj.style.top + 150;        // put the graphic 150px below the btn


    the obj.style.top returns a string that ending with "px", when you add
    a number to it, that number will parsed to string before adding.
     
    Sister Ray, Apr 17, 2009
    #2
    1. Advertising

  3. Ynot

    Ynot Guest

    "Sister Ray" <> wrote in message
    news:...
    On Apr 17, 3:31 am, "Ynot" <> wrote:

    >> var num;
    >> var obj = document.getElementById('btn'); // can't I use this element
    >> as an object?
    >> num = obj.style.top + 150; // put the graphic 150 px below the btn

    >
    >the obj.style.top returns a string that ending with "px", when you add
    >a number to it, that number will parsed to string before adding.


    Thanks. When I wrote code to parse out the "px" from the string to add the
    numbers together, I still received an error. When I tested the string, I
    found obj.style.top is a zero-length string. Any idea what is causing this?

    Thanks.
     
    Ynot, Apr 18, 2009
    #3
  4. Ynot meinte:
    > "Sister Ray" <> wrote in message
    > news:...
    > On Apr 17, 3:31 am, "Ynot" <> wrote:
    >
    >>> var num;
    >>> var obj = document.getElementById('btn'); // can't I use this element
    >>> as an object?
    >>> num = obj.style.top + 150; // put the graphic 150 px below the btn

    >> the obj.style.top returns a string that ending with "px", when you add
    >> a number to it, that number will parsed to string before adding.

    >
    > Thanks. When I wrote code to parse out the "px" from the string to add the
    > numbers together, I still received an error. When I tested the string, I
    > found obj.style.top is a zero-length string. Any idea what is causing this?
    >
    > Thanks.


    The position was never set before either by assigning a value to
    element.style.top or setting top with CSS. The "real" position can be
    obtained by retrieving element.offsetTop and iterating through its
    offsetParent elements.

    Gregor


    --
    http://www.gregorkofler.com
    http://web.gregorkofler.com - vxJS, a JS lib in progress
     
    Gregor Kofler, Apr 18, 2009
    #4
  5. Ynot

    Ynot Guest

    "Gregor Kofler" <> wrote in message
    news:49ea3680$0$4355> The position was never set before either by assigning
    a value to
    > element.style.top or setting top with CSS. The "real" position can be
    > obtained by retrieving element.offsetTop and iterating through its
    > offsetParent elements.


    Thanks. Got it working now.
     
    Ynot, Apr 18, 2009
    #5
  6. Gregor Kofler wrote:
    > Ynot meinte:
    >> "Sister Ray" <> wrote in message
    >> news:...
    >> On Apr 17, 3:31 am, "Ynot" <> wrote:
    >>
    >>>> var num;
    >>>> var obj = document.getElementById('btn'); // can't I use this element
    >>>> as an object?
    >>>> num = obj.style.top + 150; // put the graphic 150 px below the btn
    >>> the obj.style.top returns a string that ending with "px", when you add
    >>> a number to it, that number will parsed to string before adding.

    >> Thanks. When I wrote code to parse out the "px" from the string to add the
    >> numbers together, I still received an error. When I tested the string, I
    >> found obj.style.top is a zero-length string. Any idea what is causing this?
    >>
    >> Thanks.

    >
    > The position was never set before either by assigning a value to
    > element.style.top or setting top with CSS. The "real" position can be
    > obtained by retrieving element.offsetTop and iterating through its
    > offsetParent elements.
    >


    Ah, if only that really worked.

    offsetTop:
    | Retrieves the calculated top position of the object relative to the
    | layout or coordinate parent, as specified by the offsetParent
    | property.

    offsetParent:
    | offsetParent Property
    |
    | Retrieves a reference to the container object that defines the
    | offsetTop and offsetLeft properties of the object.

    Chicken and the egg.

    Since a "layout or coordinate parent" is not defined, we can't really be
    certain what the offsetTop is measured from.

    There are many inconsistencies and offsetTop is not generally reliable.

    Capability tests can determine what offsetTop returns in different
    scenarios.

    The border-top-width of the offsetParent must also be added. This is
    exposed as "clientTop" in IE, where currentStyle.borderTop might be
    "auto". There is also a clientLeft property, but no clientRight or
    clientBottom.

    Method getBoundingClientRect is less trouble, where supported.

    Garrett
     
    Garrett Smith, Apr 18, 2009
    #6
  7. Ynot

    David Mark Guest

    On Apr 18, 6:26 pm, Garrett Smith <> wrote:
    > Gregor Kofler wrote:
    > > Ynot meinte:
    > >> "Sister Ray" <> wrote in message
    > >>news:....
    > >> On Apr 17, 3:31 am, "Ynot" <> wrote:

    >
    > >>>> var num;
    > >>>> var obj = document.getElementById('btn'); // can't I use this element
    > >>>> as an object?
    > >>>> num = obj.style.top + 150; // put the graphic 150 px below the btn
    > >>> the obj.style.top returns a string that ending with "px", when you add
    > >>> a number to it, that number will parsed to string before adding.
    > >> Thanks.  When I wrote code to parse out the "px" from the string to add the
    > >> numbers together, I still received an error.  When I tested the string, I
    > >> found obj.style.top is a zero-length string.  Any idea what is causing this?

    >
    > >> Thanks.

    >
    > > The position was never set before either by assigning a value to
    > > element.style.top or setting top with CSS. The "real" position can be
    > > obtained by retrieving element.offsetTop and iterating through its
    > > offsetParent elements.

    >
    > Ah, if only that really worked.
    >
    > offsetTop:
    > | Retrieves the calculated top position of the object relative to the
    > | layout or coordinate parent, as specified by the offsetParent
    > | property.
    >
    > offsetParent:
    > | offsetParent Property
    > |
    > | Retrieves a reference to the container object that defines the
    > | offsetTop and offsetLeft properties of the object.
    >
    > Chicken and the egg.
    >
    > Since a "layout or coordinate parent" is not defined, we can't really be
    > certain what the offsetTop is measured from.
    >
    > There are many inconsistencies and offsetTop is not generally reliable.
    >
    > Capability tests can determine what offsetTop returns in different
    > scenarios.
    >
    > The border-top-width of the offsetParent must also be added. This is
    > exposed as "clientTop" in IE, where currentStyle.borderTop might be
    > "auto". There is also a clientLeft property, but no clientRight or
    > clientBottom.
    >
    > Method getBoundingClientRect is less trouble, where supported.


    The answer is to measure only as far as a positioned ancestor. Leave
    borders out of it and the solution reduces to one or two lines. If
    your containing elements may have borders, there is a trivial feature
    test for that. Anything that attempts to measure from the tip of the
    documentElement is folly in comparison.
     
    David Mark, Apr 19, 2009
    #7
  8. HEY! I'm interested in this problem too...

    On Apr 18, 7:25 pm, David Mark <> wrote:

    > The answer is to measure only as far as a positioned ancestor.  Leave
    > borders out of it and the solution reduces to one or two lines.  If
    > your containing elements may have borders, there is a trivial feature
    > test for that.  Anything that attempts to measure from the tip of the
    > documentElement is folly in comparison.


    Sounds great! Do you have any pointers to a good
    function implementation that does that?

    Thanks, Aaron Watters
    http://aaron.oirt.rutgers.edu/myapp/docs/W1500.whyIsWhiffCool

    ===
    less is more
     
    Aaron Watters, Apr 19, 2009
    #8
  9. Ynot

    David Mark Guest

    On Apr 18, 9:56 pm, Aaron Watters <> wrote:
    > HEY! I'm interested in this problem too...
    >
    > On Apr 18, 7:25 pm, David Mark <> wrote:
    >
    > > The answer is to measure only as far as a positioned ancestor.  Leave
    > > borders out of it and the solution reduces to one or two lines.  If
    > > your containing elements may have borders, there is a trivial feature
    > > test for that.  Anything that attempts to measure from the tip of the
    > > documentElement is folly in comparison.

    >
    > Sounds great!  Do you have any pointers to a good
    > function implementation that does that?


    That does what exactly? I am guessing you envision a scenario where
    you will have an element with a positioned ancestor and you want to
    add up offsetLeft/Top properties, starting with the former and ending
    at the latter. Some or all of these elements may have borders
    (something you can easily design out of the system.) Do you need help
    with the loop or the feature test for borders? The function should
    look something like:

    function elementOffsets(el, elAncestor) {
    ...
    }

    Of course, you won't need a loop in cases where the element is a child
    of its positioned ancestor. In that case, barring borders, the
    offsetLeft/Top properties suffice. Now there is a case to shoot for
    at the design stage.

    In contrast, the popular alternative of measuring everything from the
    document "origin" and adjusting for every known variation and browser
    quirk is clearly something to avoid at the design stage.

    http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/9ba20706f3b3fc73#

    Trying to solve every conceivable problem for every conceivable case
    is an inconceivable waste of time (not to mention space.) Hard to
    understand why neophytes who can't deal with the problems on their own
    plate would try to solve similar issues for everybody else. The
    phenomenon is not relegated solely to browser scripting, it is just
    the worst sort of discipline to withstand such hubris.
     
    David Mark, Apr 19, 2009
    #9
  10. David Mark wrote:
    > On Apr 18, 6:26 pm, Garrett Smith <> wrote:
    >> Gregor Kofler wrote:
    >>> Ynot meinte:
    >>>> "Sister Ray" <> wrote in message
    >>>> news:...
    >>>> On Apr 17, 3:31 am, "Ynot" <> wrote:
    >>>>>> var num;
    >>>>>> var obj = document.getElementById('btn'); // can't I use this element
    >>>>>> as an object?
    >>>>>> num = obj.style.top + 150; // put the graphic 150 px below the btn
    >>>>> the obj.style.top returns a string that ending with "px", when you add
    >>>>> a number to it, that number will parsed to string before adding.
    >>>> Thanks. When I wrote code to parse out the "px" from the string to add the
    >>>> numbers together, I still received an error. When I tested the string, I
    >>>> found obj.style.top is a zero-length string. Any idea what is causing this?
    >>>> Thanks.
    >>> The position was never set before either by assigning a value to
    >>> element.style.top or setting top with CSS. The "real" position can be
    >>> obtained by retrieving element.offsetTop and iterating through its
    >>> offsetParent elements.

    >> Ah, if only that really worked.
    >>
    >> offsetTop:
    >> | Retrieves the calculated top position of the object relative to the
    >> | layout or coordinate parent, as specified by the offsetParent
    >> | property.
    >>
    >> offsetParent:
    >> | offsetParent Property
    >> |
    >> | Retrieves a reference to the container object that defines the
    >> | offsetTop and offsetLeft properties of the object.
    >>
    >> Chicken and the egg.
    >>
    >> Since a "layout or coordinate parent" is not defined, we can't really be
    >> certain what the offsetTop is measured from.
    >>
    >> There are many inconsistencies and offsetTop is not generally reliable.
    >>
    >> Capability tests can determine what offsetTop returns in different
    >> scenarios.
    >>
    >> The border-top-width of the offsetParent must also be added. This is
    >> exposed as "clientTop" in IE, where currentStyle.borderTop might be
    >> "auto". There is also a clientLeft property, but no clientRight or
    >> clientBottom.
    >>
    >> Method getBoundingClientRect is less trouble, where supported.

    >
    > The answer is to measure only as far as a positioned ancestor. Leave
    > borders out of it and the solution reduces to one or two lines. If
    > your containing elements may have borders, there is a trivial feature
    > test for that. Anything that attempts to measure from the tip of the
    > documentElement is folly in comparison.


    How do you test whether or not a browser has included borders in its
    calculations?

    Andrew Poulos
     
    Andrew Poulos, Apr 19, 2009
    #10
  11. Ynot

    David Mark Guest

    On Apr 18, 11:15 pm, Andrew Poulos <> wrote:
    > David Mark wrote:
    > > On Apr 18, 6:26 pm, Garrett Smith <> wrote:
    > >> Gregor Kofler wrote:
    > >>> Ynot meinte:
    > >>>> "Sister Ray" <> wrote in message
    > >>>>news:...
    > >>>> On Apr 17, 3:31 am, "Ynot" <> wrote:
    > >>>>>> var num;
    > >>>>>> var obj = document.getElementById('btn'); // can't I use this element
    > >>>>>> as an object?
    > >>>>>> num = obj.style.top + 150; // put the graphic 150 px below the btn
    > >>>>> the obj.style.top returns a string that ending with "px", when you add
    > >>>>> a number to it, that number will parsed to string before adding.
    > >>>> Thanks.  When I wrote code to parse out the "px" from the string to add the
    > >>>> numbers together, I still received an error.  When I tested the string, I
    > >>>> found obj.style.top is a zero-length string.  Any idea what is causing this?
    > >>>> Thanks.
    > >>> The position was never set before either by assigning a value to
    > >>> element.style.top or setting top with CSS. The "real" position can be
    > >>> obtained by retrieving element.offsetTop and iterating through its
    > >>> offsetParent elements.
    > >> Ah, if only that really worked.

    >
    > >> offsetTop:
    > >> | Retrieves the calculated top position of the object relative to the
    > >> | layout or coordinate parent, as specified by the offsetParent
    > >> | property.

    >
    > >> offsetParent:
    > >> | offsetParent Property
    > >> |
    > >> | Retrieves a reference to the container object that defines the
    > >> | offsetTop and offsetLeft properties of the object.

    >
    > >> Chicken and the egg.

    >
    > >> Since a "layout or coordinate parent" is not defined, we can't really be
    > >> certain what the offsetTop is measured from.

    >
    > >> There are many inconsistencies and offsetTop is not generally reliable..

    >
    > >> Capability tests can determine what offsetTop returns in different
    > >> scenarios.

    >
    > >> The border-top-width of the offsetParent must also be added. This is
    > >> exposed as "clientTop" in IE, where currentStyle.borderTop might be
    > >> "auto". There is also a clientLeft property, but no clientRight or
    > >> clientBottom.

    >
    > >> Method getBoundingClientRect is less trouble, where supported.

    >
    > > The answer is to measure only as far as a positioned ancestor.  Leave
    > > borders out of it and the solution reduces to one or two lines.  If
    > > your containing elements may have borders, there is a trivial feature
    > > test for that.  Anything that attempts to measure from the tip of the
    > > documentElement is folly in comparison.

    >
    > How do you test whether or not a browser has included borders in its
    > calculations?


    Well, you will need to create two DIV's.

    var el = document.createElement('div');
    var elContainer = document.createElement('div');

    Position them both absolutely.

    el.style.position = elContainer.style.position = 'absolute';

    Position both at (0, 0):

    el.style.left = elContainer.style.left = '0';
    el.style.top = elContainer.style.top = '0';

    Clear margins:

    el.style.margin = elContainer.style.margin = '0';

    Give one a border:

    elContainer.style.border = 'solid 1px';

    Append one to the other.

    elContainer.appendChild(el);

    Append the container to the body:

    document.body.appendChild(elContainer);

    Before proceeding, ensure that the offset* properties are featured as
    expected.

    if (typeof el.offsetTop == 'number') {

    (I'm sure you can figure out what to check at this point.)

    Remove the temporary element. It won't have been rendered at this
    point and it is best to keep it that way. Call a function during this
    process and it will render, which requires setting its visibility to
    hidden.

    document.body.removeChild(elContainer);

    Also, it never hurts (and may help) to discard objects when finished:

    el = elContainer = null;

    There is a version of this in my library, as well as a less
    generalized implementation in an earlier popup menu script that was
    posted here in 2007. There is also a nearly identical homage (in
    somewhat less proficient script) in the new jQuery:

    rules = { position: 'absolute', top: 0, left: 0, margin: 0, border:
    0, width: '1px', height: '1px', visibility: 'hidden' };
    for ( prop in rules ) container.style[prop] = rules[prop];

    container.innerHTML = html;
    body.insertBefore(container, body.firstChild);
    innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td =
    innerDiv.nextSibling.firstChild.firstChild;

    this.doesNotAddBorder = (checkDiv.offsetTop !== 5);

    Creates an extraneous DIV, adds dimensions to the container and
    inexplicably uses insertBefore rather than appendChild. And, of
    course, it bets everything on the unpredictable and non-standard
    innerHTML property. (!) I did something similar with the style
    assignments, but I am sure the for-in loop was *filtered*.

    Their pre-epiphany version(s) use $.browser.opera or some such
    nonsense. I guess we know where they go for epiphanies.
    Unfortunately, they botched the translation again.
     
    David Mark, Apr 19, 2009
    #11
  12. David Mark wrote:
    > On Apr 18, 11:15 pm, Andrew Poulos <> wrote:


    >> How do you test whether or not a browser has included borders in its
    >> calculations?

    >
    > Well, you will need to create two DIV's.
    >
    > var el = document.createElement('div');
    > var elContainer = document.createElement('div');
    >
    > Position them both absolutely.
    >
    > el.style.position = elContainer.style.position = 'absolute';
    >
    > Position both at (0, 0):
    >
    > el.style.left = elContainer.style.left = '0';
    > el.style.top = elContainer.style.top = '0';
    >
    > Clear margins:
    >
    > el.style.margin = elContainer.style.margin = '0';
    >
    > Give one a border:
    >
    > elContainer.style.border = 'solid 1px';
    >
    > Append one to the other.
    >
    > elContainer.appendChild(el);
    >
    > Append the container to the body:
    >
    > document.body.appendChild(elContainer);
    >
    > Before proceeding, ensure that the offset* properties are featured as
    > expected.
    >
    > if (typeof el.offsetTop == 'number') {
    >
    > (I'm sure you can figure out what to check at this point.)


    This is one of things that is obvious, once I've seen it. Thanks.

    Andrew Poulos
     
    Andrew Poulos, Apr 19, 2009
    #12
  13. Garrett Smith meinte:
    > Gregor Kofler wrote:


    >> The position was never set before either by assigning a value to
    >> element.style.top or setting top with CSS. The "real" position can be
    >> obtained by retrieving element.offsetTop and iterating through its
    >> offsetParent elements.
    >>

    >
    > Ah, if only that really worked.


    [snip]

    Agreed. I had rather focused onto the "issue" that element.style.top is
    empty.

    Gregor

    --
    http://www.gregorkofler.com
    http://web.gregorkofler.com - vxJS, a JS lib in progress
     
    Gregor Kofler, Apr 19, 2009
    #13
  14. Ynot

    SAM Guest

    Le 4/19/09 12:12 AM, Ynot a écrit :
    > "Gregor Kofler" <> wrote in message
    > news:49ea3680$0$4355> The position was never set before either by assigning
    > a value to
    >> element.style.top or setting top with CSS. The "real" position can be
    >> obtained by retrieving element.offsetTop and iterating through its
    >> offsetParent elements.

    >
    > Thanks. Got it working now.


    And ... may we see it ?

    --
    sm
     
    SAM, Apr 19, 2009
    #14
  15. Ynot

    Ynot Guest

    "SAM" <> wrote in message
    news:49eaf4cf$0$17073
    >> Thanks. Got it working now.

    >
    > And ... may we see it ?


    Good idea. I'll clean up the code and post it on my friend's new site I'm
    building these apps for, then post a link to it here. Might take a week or
    more. My friend is still negotiating a price for the domain name. The
    owner has been squatting on it for 11 years and never built a site. I think
    she's never sold it because she wants too much money.
     
    Ynot, Apr 21, 2009
    #15
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Luqman
    Replies:
    1
    Views:
    657
    Luqman
    Feb 7, 2006
  2. James Wong
    Replies:
    4
    Views:
    500
    James Wong
    Jul 14, 2004
  3. Replies:
    3
    Views:
    184
  4. James Black
    Replies:
    0
    Views:
    403
    James Black
    May 28, 2006
  5. brendan
    Replies:
    0
    Views:
    198
    brendan
    Aug 29, 2006
Loading...

Share This Page