Get Scrollbar Position

Discussion in 'Javascript' started by Jeff Johnson, Jan 27, 2004.

  1. Jeff Johnson

    Jeff Johnson Guest

    Hi All,

    I'm setting a <div> on a page on a lengthy page with a great deal of
    text. I want the div to land where the user can see it. I need to
    capture the vertical scrollbar position and use that integer to set
    the 'Y' coordinate for the div.

    Can this be done? If so, how?

    If not, any other suggestions?

    Thanks,

    Jeff
     
    Jeff Johnson, Jan 27, 2004
    #1
    1. Advertisements

  2. Jeff Johnson

    DJ WIce Guest

    : I'm setting a <div> on a page on a lengthy page with a great deal of
    : text. I want the div to land where the user can see it. I need to
    : capture the vertical scrollbar position and use that integer to set
    : the 'Y' coordinate for the div.

    let x, y be the mouse position.
    let zoom_factor be the % in MSIE that the body content is zoomed
    (
    document.body.style.setAttribute('zoom', zoom_factor+'%');
    ).
    let 'contextmenu' be the ID of your DIV.

    xOff = parseInt(document.getElementById('contenxtmenu').style.width) -
    (document.all?document.body.scrollLeft:window.pageXOffset);
    yOff = parseInt(document.getElementById('contenxtmenu').style.height) -
    (document.all?document.body.scrollTop:window.pageYOffset);
    document.getElementById("contenxtmenu").style.top =
    Math.min(parseInt(y/zoom_factor*100),document.body.clientHeight-yOff)+"px";;
    document.getElementById("contenxtmenu").style.left =
    Math.min(parseInt(x/zoom_factor*100),document.body.clientWidth-xOff)+"px";


    Then your div will be placed next to the mouse, but always fully on screen.
    If you don't zoom and don't mind the mouse; replace y/zoom_factor*100
    and x/zoom_factor*100 by the prefered y and x location of your
    <div> on your page.

    Wouter
     
    DJ WIce, Jan 27, 2004
    #2
    1. Advertisements

  3. Jeff Johnson

    DU Guest

    zoom is only supported by MSIE 5.5 and MSIE 6.
    As written, you will only support backward compatible rendering mode in
    MSIE 6 where the root element is not the body. Your script might be
    interesting but it has limited scope/support among current browsers.

    DU
     
    DU, Jan 28, 2004
    #3
  4. Jeff Johnson

    DJ WIce Guest

    : As written, you will only support backward compatible rendering mode in
    : MSIE 6 where the root element is not the body. Your script might be
    : interesting but it has limited scope/support among current browsers.
    Well, it's tested in Mozilla 1.3 and MSIE 5+ ...
    And also om NN 7 and MSIE 6
    (see http://www.djwice.com/contextmenu.html )

    The zoom_factor value is default set to 100, so when the zoom function is
    not implemented, it will not be changed, and the position values stay
    (nearly) unchanged.

    Wouter
     
    DJ WIce, Jan 28, 2004
    #4
  5. JRS: In article <bv6fdp$ebt$>, seen in
    Eschew non-standard quotemarks.


    ISTM that the FAQ should have something on when parseInt should not be
    used.

    AFAICS, the first two superfluously call for conversion to Number (the
    subtraction does that, if it is needed); and the second two should be
    Math.floor.

    AFAICS, I've only once found a case where parseInt is worthwhile, other
    than where the base is a variable :

    var T = parseInt(new Date(2e9).toLocaleString()) // ~ 1970-01-24
    T = T<9 ? "US" : T>99 ? "ISO" : "UK" // US MDY, UK DMY, ISO YMD
     
    Dr John Stockton, Jan 28, 2004
    #5
  6. <snip>

    :) Done. The notes I wrote for section 4.21 (actually a more general
    discussion of type-converting with JavaScript) currently include the
    paragraph:-

    |parseInt is occasionally used as a means of turning a
    |floating point number into an integer. It is very ill suited
    |to that task because if its argument is of numeric type it
    |will first be converted into a string and then parsed as a
    |number, very inefficient. This can produce very wrong
    |results with numbers such as 2e-200, for which the nearest
    |integer is zero, but with which parseInt returns 2. For
    |rounding numbers to integers one of Math.round, Math.ceil
    |and Math.floor are preferable, and for a desired result
    |that can be expressed as a 32 bit signed integer the
    |bitwise operation described below might also suite.

    (There are additional notes on how the parsing is done, etc. in the
    section on parseFloat)

    The bitwise operation mentioned is OR zero. Which truncates floating
    point numbers to integers but might be well suited to the situation in
    the preceding posted code as the output is expected to be screen
    co-ordinates so a result restricted to a 32 bit signed integer would be
    expected anyway and it is quicker to execute than Math.floor.

    Richard.
     
    Richard Cornford, Jan 28, 2004
    #6
  7. Jeff Johnson

    DJ WIce Guest

    : >: the 'Y' coordinate for the div.
    : Eschew non-standard quotemarks.
    Ah? It's better to use " in JavaScript?

    : > xOff = parseInt(document.getElementById('contenxtmenu').style.width) -
    : >(document.all?document.body.scrollLeft:window.pageXOffset);
    : AFAICS, the first two superfluously call for conversion to Number (the
    : subtraction does that, if it is needed);
    I did not know that the substraction would eliminate the px behind the
    width and convert it to a number. Thanks.

    : > document.getElementById("contenxtmenu").style.left =
    :
    : and the second two should be
    : Math.floor.
    Yeah, I was looking for trunc or something, but floor == trunc :)

    Strangely I never saw Number before, parseInt is more common used so it
    seems.
    Is Number implemented later in the JavaScript interpreter? Or is it just not
    the right function name why it's not that much used?
    I mean wat Number? I first though it generate a random number.


    Thanks,
    Wouter
     
    DJ WIce, Jan 28, 2004
    #7
  8. Jeff Johnson

    DJ WIce Guest

    : > xOff = parseInt(document.getElementById('contenxtmenu').style.width) -
    : >(document.all?document.body.scrollLeft:window.pageXOffset);
    : > yOff = parseInt(document.getElementById('contenxtmenu').style.height) -
    : >(document.all?document.body.scrollTop:window.pageYOffset);

    : AFAICS, the first two superfluously call for conversion to Number (the
    : subtraction does that, if it is needed);

    Sorry, I have to tell you it's not true for MSIE 6.028, XP:

    When I remove parseInt in the above lines it assigns NaN to xOff and yOff.
    When I replace parseInt in the above lines with Number the same happens.

    Wouter
     
    DJ WIce, Jan 28, 2004
    #8
  9. Jeff Johnson

    DU Guest

    I'm still convinced your script for zooming could be better. As coded,
    it will not support MSIE 6 for windows in standards compliant rendering
    mode. When you go:

    xOff = parseInt(document.getElementById('contenxtmenu').style.width) -
    (document.all?document.body.scrollLeft:window.pageXOffset);

    then you are not off since the root element is not the body element but
    the html element in standards compliant rendering mode for MSIE 6.

    Anyway, I failed to see why you would or should need to know the zooming
    factor of the document. The scrolled portion of the document can be
    gotten reliably with cross-browser code without any reference to the
    text zoom.

    DU
     
    DU, Jan 28, 2004
    #9
  10. Jeff Johnson

    DJ WIce Guest

    : I'm still convinced your script for zooming could be better. As coded,
    : it will not support MSIE 6 for windows in standards compliant rendering
    : mode. When you go:

    Ah, sorry I did not understand you.
    I tought you said the code does not work.
    I see you mean that the code for MSIE 6 can be optimized so it will be
    interpreted faster, am I right?

    So document.scrollLeft when it's MSIE6 and else document.body.scrollLeft
    when it's lower?
    Sorry I'm very new to differant types of rendering;
    "standards compiliant rendereing" as oposite of .. rendering ?

    : Anyway, I failed to see why you would or should need to know the zooming
    : factor of the document. The scrolled portion of the document can be
    : gotten reliably with cross-browser code without any reference to the
    : text zoom.
    Because I want to place the menu under the mouse cursor position (x, y in my
    code).
    The mouse cursor position in MSIE 6 is returned as value of the 100% mode,
    even if it's in 150% zoomed mode.
    So one needs to correct that to let the menu show up close to the cursor if
    it's on the righthand side of the document.
    (the error on the lefthand side is not very big of cause).

    Wouter
     
    DJ WIce, Jan 28, 2004
    #10
  11. Jeff Johnson

    DJ WIce Guest

    : I'm still convinced your script for zooming could be better. As coded,
    : it will not support MSIE 6 for windows in standards compliant rendering
    : mode. When you go:
    :
    : xOff = parseInt(document.getElementById('contenxtmenu').style.width) -
    : (document.all?document.body.scrollLeft:window.pageXOffset);

    So it should be like this (?):

    xOff = parseInt(document.getElementById('contenxtmenu').style.width) -
    document.documentElement?document.documentElement.scrollLeft:(document.all?d
    ocument.body.scrollLeft:window.pageXOffset);

    Or will that still triger the compilent mode?
    But will MSIE 6 then return 0 if it's in non strict mode?
    Where can I read about degenerated elements, so I can optimize the code?

    Thanks,
    Wouter
     
    DJ WIce, Jan 28, 2004
    #11
  12. JRS: In article <bv91g2$bev$1$>, seen in
    Richard Cornford
    After checking, note that OR truncates towards zero and Math.floor
    towards minus infinity.


    A list of "Maths Tricks" might be useful, including such as
    n = n & (n-1)
    which I think clears the least 1 bit, and can be looped for one-bit-
    counting. And, of course, the "default" operator.


    I'd not seen that DJW's .style.width had a trailing px.
    ISTM that there's probably nothing better than parseInt.

    Is it guaranteed that the numeric part has no leading zero, even if
    there is a leading zero in the source file?


    ISTM that you've probably done enough already, by a large margin, to
    justify a new release of the FAQ proper with an added note simply
    linking to your own index of the relevant branch of your WWW site tree;
    or to post such a note as a weekly FU to the FAQ.
     
    Dr John Stockton, Jan 29, 2004
    #12
  13. Yes that distinction does need to be noted, but positioning co-ordinates
    will tend to be >= zero as well as restricted to the 32 bit range so the
    bitwise operation seems well suited to that task.
    I like that idea, there isn't really a context to put that type of
    information into yet but there could be.
    For a width property on a style object there probably isn't, but an
    interest in the display dimensions of an element might be better
    initially directed at the offsetWidth/Height properties of the element
    itself (where supported), which is a numeric pixel value to start with.
    A quick experiment with IE 6 has setting a style.width to "021px"
    returning "21px" when read, but I doubt that it could be guaranteed that
    values assigned as strings would be normalised and stripped of
    superfluous leading zeros. I would be surprised to see leading zeros
    added to the string read from a style property (at least for
    non-floating point (e.g. with em units) values).

    OTOH if parseInt is going to be used for this task it probably should
    still be provided with the radix argument as even if the string can
    reasonably be expected to be in an unambiguous decimal format it should
    still be quicker to execute the function when it doesn't have to
    consider interpreting the string with any other radix. It doesn't save
    much work if it is the ECMAScript algorithm that is implemented but it
    will still be able to skip a couple of steps.
    It is certainly getting close, though a new version should be presented
    to the group for comment prior to updating the FAQ itself. And the notes
    will be going on Jim's server in the long term.

    Richard.
     
    Richard Cornford, Feb 1, 2004
    #13
  14. Jeff Johnson

    DJ WIce Guest

    : OTOH if parseInt is going to be used for this task it probably should
    : still be provided with the radix argument as even if the string can
    : reasonably be expected to be in an unambiguous decimal format it should
    : still be quicker to execute the function when it doesn't have to
    : consider interpreting the string with any other radix. It doesn't save
    : much work if it is the ECMAScript algorithm that is implemented but it
    : will still be able to skip a couple of steps.

    So I should use:

    parseInt(document.getElementById('contenxtmenu').style.width,10) ?

    I think if I would implement ParseInt that I would by default compile the
    first argument as a 10-base number. So giving a second argument and setting
    it to 10-base would then result in more checks.
    (I did not yet test the speed differance).

    Wouter
     
    DJ WIce, Feb 1, 2004
    #14
  15. Jeff Johnson

    DJ WIce Guest

    : OTOH if parseInt is going to be used for this task it probably should
    : still be provided with the radix argument as even if the string can
    : reasonably be expected to be in an unambiguous decimal format it should
    : still be quicker to execute the function when it doesn't have to
    : consider interpreting the string with any other radix. It doesn't save
    : much work if it is the ECMAScript algorithm that is implemented but it
    : will still be able to skip a couple of steps.

    According to
    http://www.devguru.com/Technologies/ecmascript/quickref/parseint.html
    <quote>If no radix argument is provided or if it is assigned a value of 0,
    the function tries to determine the base. If the string starts with a 1-9,
    it will be parsed as base 10. If the string starts with 0x or 0X it will be
    parsed as a hexidecimal number. If the string starts with a 0 it will be
    parsed as an octal number. (Note that just because a number starts with a
    zero, it does not mean that it is really octal.)<quote>

    The result will be 10-base. So I see parseInt is a nice function to convert
    from base x to base 10. (if above stated is true in all browsers of cause)
    :)

    Wouter
     
    DJ WIce, Feb 1, 2004
    #15
  16. The result will depend entirely on the arguments used with parseInt, but
    it will be a number.
    With JavaScript having only one number type and that being an IEEE
    double precision floating point number, there is no meaningful concept
    of converting between bases. The numbers are stored as 64 bits, in
    binary.

    parseInt is useful as a means of reading numeric values stored as
    strings in various base formats and returning numeric values from them.
    ECMA 262 formalised pre-existing behaviour for parseInt so
    implementations can be expected to be consistent (but only with the ECMA
    262 algorithm).

    Richard.
     
    Richard Cornford, Feb 1, 2004
    #16
  17. Probably. Though repetitively reading/parsing a value that will not
    change unless you actively re-set it is wasteful in itself. As is
    re-resolving the object reference whenever it is used.
    I think if I were implementing parseInt I would be attempting to fulfil
    the requirements of ECMA 262. There is not much point inventing a new
    scripting language for use in a context where a well-standardised
    language already exists and is in common use.
    The behaviour of any new scripting language you decide to implement is
    OT here.

    Richard.
     
    Richard Cornford, Feb 1, 2004
    #17
  18. Jeff Johnson

    DJ WIce Guest

    : >parseInt(document.getElementById('contenxtmenu').style.width,10) ?
    :
    : Probably. Though repetitively reading/parsing a value that will not
    : change unless you actively re-set it is wasteful in itself. As is
    : re-resolving the object reference whenever it is used.

    Oh.. if I do understand you correct:

    var MenuObject = document.getElementById('contenxtmenu');
    xOff = parseInt(MenuObject.style.width,10) -
    (document.all?document.body.scrollLeft:window.pageXOffset);
    yOff = parseInt(MenuObject.style.height,10) -
    (document.all?document.body.scrollTop:window.pageYOffset);
    MenuObject.style.top =
    Math.min(Math.floor(y/zoom_factor*100),document.body.clientHeight-yOff)+"px"
    ;;
    MenuObject.style.left =
    Math.min(Math.floor(x/zoom_factor*100),document.body.clientWidth-xOff)+"px";

    Will be faster then without replacing
    document.getElementById('contenxtmenu')
    by
    MenuObject
    ?

    Does the same hold for
    document.getElementById('contenxtmenu').style
    ?

    Because that's the only object I'll use of the
    document.getElementById('contenxtmenu') element.

    And is it smart to replace:
    document.body.scrollLeft
    by
    document.body.scrollLeft + document.documentElement.scrollLeft
    ?


    Thanks!
    Wouter
     
    DJ WIce, Feb 1, 2004
    #18
  19. Jeff Johnson

    Jim Ley Guest

    Nope, 100% 10em 33px or ...

    I'd pick something a little safer :) Of course that's a lot more
    complicated.

    Also watch out for user stylesheets overriding your contenxtmenu's
    width.

    Jim.
     
    Jim Ley, Feb 1, 2004
    #19
  20. Jeff Johnson

    DJ WIce Guest

    : >parseInt(document.getElementById('contenxtmenu').style.width,10) ?
    :
    : Nope, 100% 10em 33px or ...
    :
    : I'd pick something a little safer :) Of course that's a lot more
    : complicated.

    How can I convert a 100% to pixels for example (and the same question for em
    to px, ect.)?

    Wouter
     
    DJ WIce, Feb 1, 2004
    #20
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.