feature detection to replace use of "navigator.userAgent" in Yahoo! UI event.js?

Discussion in 'Javascript' started by petermichaux@gmail.com, Sep 1, 2006.

  1. Guest

    Hi,

    I'm picking apart the Yahoo! UI event.js library and stripping it down
    to just what I need. I'm also trying to make the parts I use better.
    I'm stumped on how to fix the code for the getPageX() method. This
    method is supposed to give the same value in IE as other browsers for
    the event position relative to the left of the page. This value will be
    greater than the position relative to the left of the browser if the
    browser is scrolled to the right. What would be the appropriate feature
    detection to use for the conditional in the following line?

    if ( this.isIE ) {

    Thank you,
    Peter


    isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),

    isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) &&
    navigator.userAgent.match(/msie/gi)),


    getPageX: function(ev) {
    var x = ev.pageX;
    if (!x && 0 !== x) {
    x = ev.clientX || 0;

    if ( this.isIE ) {
    x += this._getScroll()[1];
    }
    }
    return x;
    },

    _getScroll: function() {
    var dd = document.documentElement, db = document.body;
    if (dd && dd.scrollTop) {
    return [dd.scrollTop, dd.scrollLeft];
    } else if (db) {
    return [db.scrollTop, db.scrollLeft];
    }
    return [0, 0];
    }
    , Sep 1, 2006
    #1
    1. Advertising

  2. RobG Guest

    wrote:
    > Hi,
    >
    > I'm picking apart the Yahoo! UI event.js library and stripping it down
    > to just what I need. I'm also trying to make the parts I use better.
    > I'm stumped on how to fix the code for the getPageX() method. This
    > method is supposed to give the same value in IE as other browsers for
    > the event position relative to the left of the page. This value will be
    > greater than the position relative to the left of the browser if the
    > browser is scrolled to the right. What would be the appropriate feature
    > detection to use for the conditional in the following line?
    >
    > if ( this.isIE ) {


    Don't use browser sniffing at all, use the stuff from quirksmode for
    detecting the mouse coordinates:

    <URL: http://www.quirksmode.org/js/events_properties.html >


    Matt Kruse also has a utilities library to do much the same thing:

    <URL: http://www.javascripttoolbox.com/lib/util/ >


    [...]

    --
    Rob
    RobG, Sep 1, 2006
    #2
    1. Advertising

  3. Guest

    RobG wrote:
    > wrote:
    > > Hi,
    > >
    > > I'm picking apart the Yahoo! UI event.js library and stripping it down
    > > to just what I need. I'm also trying to make the parts I use better.
    > > I'm stumped on how to fix the code for the getPageX() method. This
    > > method is supposed to give the same value in IE as other browsers for
    > > the event position relative to the left of the page. This value will be
    > > greater than the position relative to the left of the browser if the
    > > browser is scrolled to the right. What would be the appropriate feature
    > > detection to use for the conditional in the following line?
    > >
    > > if ( this.isIE ) {

    >
    > Don't use browser sniffing at all, use the stuff from quirksmode for
    > detecting the mouse coordinates:
    >
    > <URL: http://www.quirksmode.org/js/events_properties.html >
    >
    >
    > Matt Kruse also has a utilities library to do much the same thing:
    >
    > <URL: http://www.javascripttoolbox.com/lib/util/ >


    Hi Rob,

    Thanks for the links. The quirksmode link gives a nice, concise
    solution. Trusting that it is a robust way of doing things, I ended up
    with a very short function

    getPageX: function(e) {
    if (e.pageX) {
    return e.pageX;
    } else if (e.clientX) {
    return e.clientX + document.body.scrollLeft +
    document.documentElement.scrollLeft;
    }
    },

    What to do in the case neither e.pageX nor e.clientX exist? Probably
    will never happen?

    Thanks again!
    Peter
    , Sep 1, 2006
    #3
  4. RobG Guest

    wrote:
    > RobG wrote:

    [...]
    > > Don't use browser sniffing at all, use the stuff from quirksmode for
    > > detecting the mouse coordinates:
    > >
    > > <URL: http://www.quirksmode.org/js/events_properties.html >
    > >
    > >
    > > Matt Kruse also has a utilities library to do much the same thing:
    > >
    > > <URL: http://www.javascripttoolbox.com/lib/util/ >

    >
    > Hi Rob,
    >
    > Thanks for the links. The quirksmode link gives a nice, concise
    > solution. Trusting that it is a robust way of doing things, I ended up
    > with a very short function
    >
    > getPageX: function(e) {
    > if (e.pageX) {
    > return e.pageX;
    > } else if (e.clientX) {
    > return e.clientX + document.body.scrollLeft +
    > document.documentElement.scrollLeft;
    > }
    > },


    I like use an ePos() function that returns an object with x & y
    properties that are the event co-ords - but that's just my preference.
    Then I can test the returned value simply:

    var eventXY = ePos(event);
    if (ePos){...}

    If you just return a value, then to account for the fact that zero is a
    valid return value you have to do something like:

    var eventX = getPageX(event);
    if ('number' == typeof eventX) {...}


    > What to do in the case neither e.pageX nor e.clientX exist? Probably
    > will never happen?


    Never say never :) Mobile browsers are becoming more prevelent, while
    their support for JavaScript is generally great, their scriptable DOM
    support leaves a lot to be desired.

    According to Quirksmode, pageX/clientX goes back to IE 5 and Navigator
    4, hopefully that is far enough for you. Anyhow, return some value you
    can recognise as "not supported" (say null) and deal with it in the
    calling function.

    if ('number' == typeof eventX) {
    /* do something with the returned value */
    } else {
    /* not supported, deal with it */
    }


    --
    Rob
    RobG, Sep 1, 2006
    #4
  5. wrote:
    > RobG wrote:
    > > wrote:

    <snip>
    >>> What would be the appropriate feature
    >>> detection to use for the conditional in the following line?
    >>>
    >>> if ( this.isIE ) {

    > >
    > > Don't use browser sniffing at all, use the stuff from quirksmode for
    > > detecting the mouse coordinates:
    > >
    > > <URL: http://www.quirksmode.org/js/events_properties.html >
    > >
    > >
    > > Matt Kruse also has a utilities library to do much the same thing:
    > >
    > > <URL: http://www.javascripttoolbox.com/lib/util/ >

    >
    > Hi Rob,
    >
    > Thanks for the links. The quirksmode link gives a nice, concise
    > solution. Trusting that it is a robust way of doing things, I ended up
    > with a very short function
    >
    > getPageX: function(e) {
    > if (e.pageX) {
    > return e.pageX;
    > } else if (e.clientX) {
    > return e.clientX + document.body.scrollLeft +
    > document.documentElement.scrollLeft;
    > }
    > },
    >
    > What to do in the case neither e.pageX nor e.clientX exist?
    > Probably will never happen?


    That may never happen, but a browser providing - pageX - only can still
    have its value at zero and so return undefined. It is also possible
    that the code may be exposed to a browser where - clientX - is not
    accompanied by both of - body - and - documentElement -, so error out,
    or that both of - body - and - documentElement - may be returning the
    same scroll value for the browser (that was certainly true of some
    Opera 7 releases, and usually worked as most scripts employed the first
    of the two that appeared to provide a value so it did not matter if
    both did).

    (Opera <= 6 also had a bug in that they only supported - clientX/Y - on
    events but returned page related offsets instead of window related).

    Probably a better strategy might be to stop thinking in terms of
    getting scroll positions from objects at the point of working out mouse
    offsets from the page but instead to use a reliable cross-browser
    scroll-offset reporting method and only apply it when an event only has
    - clientX/Y - available.

    <URL:
    http://jibbering.com/faq/faq_notes/not_browser_detect.html#bdScroll >

    Richard.
    Richard Cornford, Sep 1, 2006
    #5
  6. Guest

    Richard Cornford wrote:
    > wrote:
    > > RobG wrote:
    > > > wrote:

    > <snip>
    > >>> What would be the appropriate feature
    > >>> detection to use for the conditional in the following line?
    > >>>
    > >>> if ( this.isIE ) {
    > > >
    > > > Don't use browser sniffing at all, use the stuff from quirksmode for
    > > > detecting the mouse coordinates:
    > > >
    > > > <URL: http://www.quirksmode.org/js/events_properties.html >
    > > >
    > > >
    > > > Matt Kruse also has a utilities library to do much the same thing:
    > > >
    > > > <URL: http://www.javascripttoolbox.com/lib/util/ >

    > >
    > > Hi Rob,
    > >
    > > Thanks for the links. The quirksmode link gives a nice, concise
    > > solution. Trusting that it is a robust way of doing things, I ended up
    > > with a very short function
    > >
    > > getPageX: function(e) {
    > > if (e.pageX) {
    > > return e.pageX;
    > > } else if (e.clientX) {
    > > return e.clientX + document.body.scrollLeft +
    > > document.documentElement.scrollLeft;
    > > }
    > > },
    > >
    > > What to do in the case neither e.pageX nor e.clientX exist?
    > > Probably will never happen?

    >
    > That may never happen, but a browser providing - pageX - only can still
    > have its value at zero and so return undefined. It is also possible
    > that the code may be exposed to a browser where - clientX - is not
    > accompanied by both of - body - and - documentElement -, so error out,
    > or that both of - body - and - documentElement - may be returning the
    > same scroll value for the browser (that was certainly true of some
    > Opera 7 releases, and usually worked as most scripts employed the first
    > of the two that appeared to provide a value so it did not matter if
    > both did).
    >
    > (Opera <= 6 also had a bug in that they only supported - clientX/Y - on
    > events but returned page related offsets instead of window related).
    >
    > Probably a better strategy might be to stop thinking in terms of
    > getting scroll positions from objects at the point of working out mouse
    > offsets from the page but instead to use a reliable cross-browser
    > scroll-offset reporting method and only apply it when an event only has
    > - clientX/Y - available.
    >
    > <URL:
    > http://jibbering.com/faq/faq_notes/not_browser_detect.html#bdScroll >


    Hi Richard,

    Thanks for the info and the link.

    I really did think that the quirksmode way of assuming document.body
    and document.documentElement both exist seems a little suspicious.

    The link you sent is an interesting approach. It seems a bit convoluted
    but looks like it must be very efficient in use as it doesn't have to
    if-else with each call. Is this code your work?

    Thanks again,
    Peter
    , Sep 1, 2006
    #6
  7. Guest

    Richard Cornford wrote:

    > Probably a better strategy might be to stop thinking in terms of
    > getting scroll positions from objects at the point of working out mouse
    > offsets from the page but instead to use a reliable cross-browser
    > scroll-offset reporting method and only apply it when an event only has
    > - clientX/Y - available.


    Looking in Flanagan's book (4th ed p383), It looks like pageX/Y in
    Netscape 4 would also need the scroll amounts added.


    > <URL:
    > http://jibbering.com/faq/faq_notes/not_browser_detect.html#bdScroll >



    Using the function on jibbering, how does this function look?

    getPageX: function(e) {
    var x;
    if (e.pageX) {
    x=e.pageX;
    } else if (e.clientX) {
    x=e.clientX
    } else {
    return null;
    }
    return x + scrollInterface.getScrollX();
    },


    I wanted to cut this down to something like the following but I
    couldn't get it working

    getPageX: function(e) {
    var x = (e.pageX) ? e.pageX : (e.clientX) ? e.clientX : return
    null;
    return x + scrollInterface.getScrollX();
    },


    I'm still surprised that a little tasks like finding an event location
    is so challenging.

    In fact, I don't really care about supporting Netscape 4 with it's lack
    of clientX. Similarly, I don't really care about supporting browsers
    without document.getElementById().

    Thanks,
    Peter
    , Sep 1, 2006
    #7
  8. wrote:
    <snip>
    > Using the function on jibbering, how does this function
    > look?
    >
    > getPageX: function(e) {
    > var x;
    > if (e.pageX) {


    You have repeated one of the logical mistakes in the Yahoo library and
    failed to consider that a - pageX - may legitimately be numeric zero,
    which type-converts to boolean false;

    > x=e.pageX;
    > } else if (e.clientX) {
    > x=e.clientX
    > } else {
    > return null;


    NaN is the sensible value to return to indicate a failure from a
    function call that would otherwise return another numeric value, and
    the - isNaN - function is available for performing a discriminating test
    for failure on the result.

    > }
    > return x + scrollInterface.getScrollX();


    If the event object has a - pageX - property you don't want to be adding
    scroll offsets to the - x - value. That addition should be restricted to
    the - if(typeof e.clientX == 'number') - branch (if not more guarded).

    > },
    >
    >
    > I wanted to cut this down to something like the following but I
    > couldn't get it working
    >
    > getPageX: function(e) {
    > var x = (e.pageX)?e.pageX:(e.clientX)?e.clientX:return null;

    <snip>

    The - return - keyword forms a Statement, while the conditional operator
    takes Expressions as its operands. A syntax error would be expected
    here.

    return (
    (typeof e.pageX == 'number')?
    e.pageX:
    (
    (typeof e.clientX == 'number')?
    (
    e.clientX + scrollInterface.getScrollX()
    ):
    NaN
    )
    );

    - would be the single Statement formulation of your code.

    > I'm still surprised that a little tasks like finding an event
    > location is so challenging.


    You can rise to a challenge or hide from it. Why do you think the
    general standard of scripting on the Internet is so poor?

    > In fact, I don't really care about supporting Netscape 4
    > with it's lack of clientX.


    Why would that be a problem as it supports - pageX -? The code you have
    written will work fine with Netscape 4, so long as the - pageX - is not
    zero.

    > Similarly, I don't really care about supporting
    > browsers without document.getElementById().


    That attitude will get in the way of your learning browser scripting.
    Learn to design systems that still makes sense (and in e-commerce terms;
    makes money) with client-side scripting disabled and you will find
    yourself in a position to cope regardless of whether a browser
    provides - document.getElementById - or not. And in a position to make
    informed decisions about when designing/creating such a system is
    appropriate.

    Richard.
    Richard Cornford, Sep 7, 2006
    #8
  9. wrote:
    <snip>
    > I really did think that the quirksmode way of assuming
    > document.body and document.documentElement both exist
    > seems a little suspicious.


    I am not a fan of the quirksmode attitude towards browser scripting.
    There seems to be a lot of throwing up of hands in horror and then
    walking away from the problems.

    > The link you sent is an interesting approach. It seems
    > a bit convoluted


    It is convoluted, but internal complexity inside self-contained
    components that follow the logic of the problem through to the point
    where they should not need ongoing maintenance is not a great concern of
    mine. The external interface is simple and that should be the only
    concern of anyone using the component.

    > but looks like it must be very efficient in use as it
    > doesn't have to if-else with each call.


    Yes, I don't like repeating tests on each call to a function in an
    environment/context where all tests after the first a bound to return
    the same result as the first.

    > Is this code your work?


    Would that matter?

    Richard.
    Richard Cornford, Sep 7, 2006
    #9
  10. Guest

    Hi Richard,

    Thank you for the detailed reply.

    [snip]

    > > I'm still surprised that a little tasks like finding an event
    > > location is so challenging.

    >
    > You can rise to a challenge or hide from it. Why do you think the
    > general standard of scripting on the Internet is so poor?


    I definitely want to rise to the challenge. A lot of the browser
    incompatibility workarounds are quite subtle and it's great exprienced
    people here are willing to share their experience. I also think that
    the prototype.js, Scriptaculous, Yahoo! UI developers should spend more
    time here asking quesitons and reading the discussions. Perhaps they
    have to maintain an appearance of expertise.

    Peter
    , Sep 7, 2006
    #10
  11. wrote:
    <snip>
    >>> I'm still surprised that a little tasks like finding an
    >>> event location is so challenging.

    >>
    >> You can rise to a challenge or hide from it. Why do you
    >> think the general standard of scripting on the Internet
    >> is so poor?

    >
    > I definitely want to rise to the challenge. A lot of the
    > browser incompatibility workarounds are quite subtle and
    > it's great exprienced people here are willing to share
    > their experience. I also think that the prototype.js,
    > Scriptaculous, Yahoo! UI developers should spend more time
    > here asking quesitons and reading the discussions. Perhaps
    > they have to maintain an appearance of expertise.


    "Maintain an appearance" or 'maintain a self-delusion'? None of the
    people I consider experts in browser scripting would have created any of
    those, except Yahoo, but that is only because I see Yahoo's motivation
    as unrelated to what they have published.

    Richard.
    Richard Cornford, Sep 7, 2006
    #11
    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. checoo
    Replies:
    0
    Views:
    532
    checoo
    Dec 25, 2006
  2. checoo
    Replies:
    1
    Views:
    496
  3. Jan Buchwald

    navigator.userAgent

    Jan Buchwald, Aug 12, 2004, in forum: Javascript
    Replies:
    12
    Views:
    296
    Randy Webb
    Aug 14, 2004
  4. zhonghua

    about "var yahoo = window.yahoo || {}"

    zhonghua, Jul 10, 2006, in forum: Javascript
    Replies:
    2
    Views:
    106
    zhonghua
    Jul 10, 2006
  5. Peter Michaux
    Replies:
    2
    Views:
    342
    Peter Michaux
    Aug 31, 2007
Loading...

Share This Page