Tom Gullen
Tom Gullen

Reputation: 61765

Javascript firefox can't find values all other browsers do

function ganttChart(gContainerID) {

    this.gContainer = document.getElementById(gContainerID);    // The container the chart          this.gCurrentDragBar = -1;
    this.gIsDraggingBar = false;
    this.gMouseStartX = 0;
    this.gMouseStartY = 0;
    this.gBarStartX = 0;
    this.gBarStartY = 0;
    this.gBarBeingDragged;
    this.gCurrentMouseX;
    this.gCurrentMouseY;

    // On mouse move
    this.gAttatchMove = function(self) {

        self.gContainer.onmousemove = function(evt) {
            if (self.gIsDraggingBar) {

                self.gUpdateMousePos(evt);
                self.gBarBeingDragged.style.left = (self.gBarStartX - (self.gMouseStartX - self.gCurrentMouseX)) + "px";

                //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                // PRINTS MESSAGE HERE
                document.getElementById("db").innerHTML = "Bar start: " + self.gBarStartX + "<br />Mouse start:" + self.gMouseStartX + "<br />Mouse current:" + self.gCurrentMouseX;
                //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            }
        }; 
        self.gContainer.onmouseup = function() {
            self.gIsDraggingBar = false;
        };

    }
    var self = this;
    this.gAttatchMove(self);

    // Update mouse coords
    this.gUpdateMousePos = function(evt) {
        if (window.event) {
            this.gCurrentMouseX = event.x;
            this.gCurrentMouseY = event.y;
        }
        else {
            this.gCurrentMouseX = evt.x;
            this.gCurrentMouseY = evt.y;
        }
    }

    // Sets up the bar mouse events
    gSetupMouseEvents = function(gBar, i, self) {

        gBar.onmouseover = function() {
            gBarHighlight(gBar, self.gData[i][1], self.gData[i][2]);
        };
        gBar.onmouseout = function() {
            gBarUnHighlight(gBar, self.gData[i][1], self.gData[i][2]);
        };
        gBar.onmousedown = function(evt) {

            // Initialise
            self.gCurrentDragBar = i;
            self.gBarBeingDragged = document.getElementById("gBar" + i);
            self.gIsDraggingBar = true;

            // Set initial positions
            self.gUpdateMousePos(evt);
            self.gMouseStartX = self.gCurrentMouseX;
            self.gMouseStartY = self.gCurrentMouseY;
            self.gBarStartX = self.gBarBeingDragged.offsetLeft;
            self.gBatStartY = self.gBarBeingDragged.offsetTop;
        };


    }

}

The values printed out are:

Firefox:

Bar start: 0
Mouse start:undefined
Mouse current:undefined

Chrome

Bar start: 0
Mouse start:163
Mouse current:165

IE

Bar start: 1
Mouse start:3
Mouse current:19

I'm not worried about varying values between IE/Chrome I can debug that (just the way mouse position is interpreted) but firefox not picking any values is confusing me!

Upvotes: 1

Views: 324

Answers (2)

bobince
bobince

Reputation: 536615

    this.gCurrentMouseX = evt.x;

You don't want to use .x. It doesn't exist on a standard DOM MouseEvent object (which is why Firefox doesn't have it) and even in IE, it's usually not what you want. It's relative to the nearest positioned ancestor, where the meaning of ‘positioned’ may vary. It's generally better to get page-relative co-ordinates.

Unfortunately, the pageX property that gives you this is also not a standard Event property, so although it is supported by IE9, Firefox, WebKit etc, you can't guarantee it's there. You can instead use clientX, which is standard, but is relative to the viewport, so to correct it in case the viewport has scrolled, you have to add the scrollLeft of the documentElement (unless you're in IE Quirks Mode, in which case it's the body instead... don't be in Quirks Mode!).

(The other standard positioning property on MouseEvent is screenX, but that's largely useless except for positioning popups. There are also the non-standard properties offsetX and layerX which are even more useless.)

    if (window.event) {

Better to test for the standard first (evt not being undefined), and only fall back to window.event for IE<9. Otherwise you may not get what you expect on browsers that support both, or where there's something else (eg a variable or element) defined called event.

// Update mouse coords
this.gUpdateMousePos = function(evt) {
    if (evt===undefined) evt= window.event;

    if ('pageX' in evt) {
        this.gCurrentMouseX = evt.pageX;
        this.gCurrentMouseY = evt.pageY;
    } else {
        this.gCurrentMouseX = evt.clientX+document.documentElement.scrollLeft;
        this.gCurrentMouseY = evt.clientY+document.documentElement.scrollTop;
    }
}

This gives you page-relative co-ordinates. If you want to calculate position relative to a particular element you then have to subtract the page-relative co-ordinates of that element, typically using an offsetLeft/offsetParent loop. Though there are lots more potential browser problems there too. Sigh. Frameworks can help here. Although to be honest most of them still trip up on some of the uglier corner cases.

(It would be jolly nice if some helpful organisation would specify MouseEvent pageX/pageY as being standard, and add element/view pageLeft/pageTop properties to match... I can dream...)

Upvotes: 1

Pointy
Pointy

Reputation: 413936

The mouse position is given in the "clientX" and "clientY" properties of the event object, not "x" and "y".

Upvotes: 3

Related Questions