/*
** ELEMENT
**     mouse_position.js
**
** AUTHOR
**     arvid berdahl - berdahl@phatcox.net
**
** LAST MODIFIED
**     6th June 2006
**
** COMMENTS
**     this element monitors mouse movements on the active document.
**     it allows element-scripts to call: __add_mouse_func, with
**     6 arguments: (id, x1, y2, x2, y2, func), where 'func' will
**     be called when the mouse cursor hovers over id's area.
**
**     element-scripts can also call: __remove_mouse_func, with a
**     corresponding 'id' to remove each individual behaviour.
*/

// global variable declarations
var xMousePos = 0;  // x mouse position (main document)
var yMousePos = 0;  // y mouse position (main document)
var __xMousePos = 0; // x mouse position (main div)
var __yMousePos = 0; // x mouse position (main div)
var mouse_areas = new Array(); // dynamic added mouse areas ( (id, x1, y1, x2, y2, func1, status, x3, y3, x4, y4, func2, arg), .. )
var mouse_areas_disabled = 0;  // flag for which all mouse areas are disabled or enabled

/*
** FUNCTION
**     __mouse_areas_disable()
**
** COMMENTS
**     disables all mouse areas and trigger "off" func on active mouse areas (if any).
**
**     this function is useful, if you want to disable existing mouse areas when
**     entering an overlaying iframe element etc.
*/

function __mouse_areas_disable() {

    // make a duplicate backup of existing mouse areas and call "off" func on active mouse areas (if any)
    for (_nr = 0; _nr < mouse_areas.length; _nr++) {
        
        // call "off" function on any active mouse areas
        if (mouse_areas[_nr][6]) {
            mouse_areas[_nr][11](mouse_areas[_nr][12]);
            mouse_areas[_nr][6] = 0;
        }
    }

    // set disabled flag
    mouse_areas_disabled = 1;
}

/*
** FUNCTION
**     __mouse_areas_enable()
**
** COMMENTS
**     re-enable all registered mouse areas
*/

function __mouse_areas_enable() {

    // re-add backup mouse areas
    for (_nr = 0; _nr < mouse_areas.length; _nr++) {

        // call "on" function on any "hovering" mouse areas (if any)
        if (query_mouse_area(mouse_areas[_nr][1], mouse_areas[_nr][2], mouse_areas[_nr][3], mouse_areas[_nr][4])) {
            mouse_areas[_nr][5](mouse_areas[_nr][12]);
            mouse_areas[_nr][6] = 1;
        }
    }

    // clear disabled flag
    mouse_areas_disabled = 0;
}

/* FUNCTION
**     __add_mouse_func(_id, _x1, _y1, _x2, _y2, _func1, _x3, _y3, _x4, _y4, _func2, arg)
**
** COMMENTS
**     you can call this function to add a new 'mouse area' for which
**     '_func()' will be called when the mouse pointer hovers over.
**     You may also define 'max_y-20', 'max_y+20' for the y1, and y1
**     where 'max_y' will be replaced with the current pageHeight().
**
**     Now _x3, _y3, _x4, _y4 should in most situations be identical to
**     the _x1, _y1, _x2, _y2 where '_func2' is the function called 
**     when the mouse pointer leaves this area. However, in some occations
**     you might want to change the area of effect, and by parsing
**     individual areas you can do this easily.
**
**     last argument 'arg' should be set to 0 if you do not need to specify
**     an argument to be parsed to the functions called.
**
** NOTE
**     all defined 'mouse_areas' will be checked every time the mouse
**     cursor is moved!
*/

function __add_mouse_func(_id, _x1, _y1, _x2, _y2, _func1, _x3, _y3, _x4, _y4, _func2, arg) {
    var _amc = new Array(_id, _x1, _y1, _x2, _y2, _func1, 0, _x3, _y3, _x4, _y4, _func2, arg);

    // if it already exists, ignore call: (added 16th july, 2006 -- berdahl).
    if (mouse_areas.length > 0) {
        for (_nr = 0; _nr < mouse_areas.length; _nr++) {
            if (_id == mouse_areas[_nr][0])
                return false;
        }
    }

    mouse_areas[mouse_areas.length] = _amc;
}

/*
** FUNCTION
**     __remove_mouse_func(_id)
**
** COMMENTS
**     you can call this function to remove an already defined 
**     'mouse_area', where '_id' is the name you gave that individual
**     mouse area.
**
** NOTE
**     after removing 'mouse_areas' , it will be permanently deleted
**     and mouse events will no longer trigger functions previously
**     defined for this area.
**
**     NB: If second argument 'flag' is given and this mouse_area is 
**         currently in "hoverstate" (active), the function will call
**         the corresponding mouse_areas 'off' function before removal.
*/

function __remove_mouse_func(_id, flag) {
    var _nr;

    if (mouse_areas.length <= 0)
        return false;

    for (_nr = 0; _nr < mouse_areas.length; _nr++) {
        if (_id == mouse_areas[_nr][0]) {
            if (mouse_areas[_nr][6])
                mouse_areas[_nr][11](mouse_areas[_nr][12]);
            mouse_areas.splice(_nr, 1);
            return _nr;
        }
    }
    
    return -1;
}

/*
** FUNCTION
**     __change_mouse_func(_id, _x1, _y1, _x2, _y2, _func1, _x3, _y3, _x4, _y4, _func2, arg)
**
** COMMENTS
**     you can use this function to change the data for a specific _id mouse-area.
**     (easier than first calling __remove_mouse_func, then set your new data
**      by using __add_mouse_func).
*/

function __change_mouse_func(_id, _x1, _y1, _x2, _y2, _func1, _x3, _y3, _x4, _y4, _func2, arg) {
    var _nr;
    
    if (mouse_areas.length <= 0)
        return false;
    
    for (_nr = 0; _nr < mouse_areas.length; _nr++) {
    	if (_id == mouse_areas[_nr][0]) {
            var _amc = new Array(_id, _x1, _y1, _x2, _y2, _func1, 0, _x3, _y3, _x4, _y4, _func2, arg);

      	    // set the corresponding menu to 'off' status (in case we are currently hovering and mouse-area differs
      	    mouse_areas[_nr][ 6] = 0;                   // set status off
      	    mouse_areas[_nr][11](mouse_areas[_nr][12]); // trigger off function call

    	    // set its new data
    	    mouse_areas[_nr] = _amc;
    	    return _nr;
    	}
    }

    return -1;
}

/*
** FUNCTION
**     function __check_all_areas()
**
** COMMENTS
**     called every time the mouse cursor is moved in the active document.
**     It will loop through all registered 'mouse_areas', and attempt call
**     corresponding functions to active/unactive mouse areas.
*/

function __check_all_areas() {
    var _mouse_x1, _mouse_y1, _mouse_x2, _mouse_y2, _f1;
    var _mouse_x3, _mouse_y3, _mouse_x4, _mouse_y4, _f2;
    var _nr, _id;

    if (mouse_areas.length <= 0 || mouse_areas_disabled)
        return false;

    for (_nr = 0; _nr < mouse_areas.length; _nr++) {

        _mouse_x1 = mouse_areas[_nr][ 1];
        _mouse_y1 = mouse_areas[_nr][ 2];
        _mouse_x2 = mouse_areas[_nr][ 3];
        _mouse_y2 = mouse_areas[_nr][ 4];
        _f1 = mouse_areas[_nr][ 5];

        _mouse_x3 = mouse_areas[_nr][ 7];
        _mouse_y3 = mouse_areas[_nr][ 8];
        _mouse_x4 = mouse_areas[_nr][ 9];
        _mouse_y4 = mouse_areas[_nr][10];
        _f2 = mouse_areas[_nr][11];
        
        // now check if current mouse position triggers f1 function (status on)
        if (query_mouse_area(_mouse_x1, _mouse_y1, _mouse_x2, _mouse_y2)) {
            if (!mouse_areas[_nr][6]) {
            	mouse_areas[_nr][6] = 1;   // set status on
                _f1(mouse_areas[_nr][12]); // function call
            }
        // orelse, whether it triggers f2 function (status off)
        } else if (!query_mouse_area(_mouse_x3, _mouse_y3, _mouse_x4, _mouse_y4)) {
        	if (mouse_areas[_nr][6]) {
        	    mouse_areas[_nr][6] = 0;   // set status off
        	    _f2(mouse_areas[_nr][12]); // function call
        	}
        }
    }
}

/*
** FUNCTION
**     function query_mouse_area(_x1, _y1, _x2, _y2)
**
** COMMENTS
**     this function checks whether mouse cursor is within a given area on the screen.
*/

function query_mouse_area(_mouse_x1, _mouse_y1, _mouse_x2, _mouse_y2) {

    // check for max_y string in _mouse_y1
    if (typeof(_mouse_y1) == "string" && _mouse_y1.indexOf("max_y") > -1) {
        _val = pageHeight();
        _mouse_y1 = _mouse_y1.replace("max_y", ""); // remove 'maxy' reference tag from string
        _val += parseInt(_mouse_y1); // add remaining value modifier ("+20", "-20") etc
        _mouse_y1 = _val;
    }

    // check for max_y string in _mouse_y2
    if (typeof(_mouse_y2) == "string" && _mouse_y2.indexOf("max_y") > -1) {
        _val = pageHeight();
        _mouse_y2 = _mouse_y2.replace("max_y", ""); // remove 'maxy' reference tag from string
        _val += parseInt(_mouse_y2); // add remaining value modifier ("+20", "-20") etc
        _mouse_y2 = _val;
    }
  
    // check for center string in _mouse_y1
    if (typeof(_mouse_y1) == "string" && _mouse_y1.indexOf("center") > -1) {
        _val = pageHeight() / 2;
        _mouse_y1 = _mouse_y1.replace("center", ""); // remove 'center' reference tag from string
        _val += parseInt(_mouse_y1); // add remaining value modifier ("+20", "-20") etc
        _mouse_y1 = _val;
    }

    // check for center string in _mouse_y2
    if (typeof(_mouse_y2) == "string" && _mouse_y2.indexOf("center") > -1) {
        _val = pageHeight() / 2;
        _mouse_y2 = _mouse_y2.replace("center", ""); // remove 'center' reference tag from string
        _val += parseInt(_mouse_y2); // add remaining value modifier ("+20", "-20") etc
        _mouse_y2 = _val;
    }

    // check for center string in _mouse_x1
    if (typeof(_mouse_x1) == "string" && _mouse_x1.indexOf("center") > -1) {
        _val = pageWidth() / 2;
        _mouse_x1 = _mouse_x1.replace("center", ""); // remove 'center' reference tag from string
        _val += parseInt(_mouse_x1); // add remaining value modifier ("+20", "-20") etc
        _mouse_x1 = _val;
    }

    // check for center string in _mouse_x2
    if (typeof(_mouse_x2) == "string" && _mouse_x2.indexOf("center") > -1) {
        _val = pageWidth() / 2;
        _mouse_x2 = _mouse_x2.replace("center", ""); // remove 'center' reference tag from string
        _val += parseInt(_mouse_x2); // add remaining value modifier ("+20", "-20") etc
        _mouse_x2 = _val;
    }

    // check for center string in _mouse_x3
    if (typeof(_mouse_x3) == "string" && _mouse_x3.indexOf("center") > -1) {
        _val = pageWidth() / 2;
        _mouse_x3 = _mouse_x3.replace("center", ""); // remove 'center' reference tag from string
        _val += parseInt(_mouse_x3); // add remaining value modifier ("+20", "-20") etc
        _mouse_x3 = _val;
    }

    // check for center string in _mouse_x4
    if (typeof(_mouse_x4) == "string" && _mouse_x4.indexOf("center") > -1) {
        _val = pageWidth() / 2;
        _mouse_x4 = _mouse_x4.replace("center", ""); // remove 'center' reference tag from string
        _val += parseInt(_mouse_x4); // add remaining value modifier ("+20", "-20") etc
        _mouse_x4 = _val;
    }

    if (xMousePos < _mouse_x1 || xMousePos > _mouse_x2)
        return false;

    if (yMousePos < _mouse_y1 || yMousePos > _mouse_y2)
        return false;

    return true;
}

/*
** FUNCTION
**     __hook_mouse_move_index(e)
**
** COMMENTS
**     this function is called when a mousemove event is registered in index.php, 
**     which is the document putting our main document into an iframe , thus having
**     its own mouse events. 
**     we now know for certain all registered 'mouse_areas' are unactive as the 
**     mouse pointer has been moved away from all mouse areas, hence we disable
**     all active mouse areas if any.
*/

function __hook_mouse_move_index(e) {
    var _nr;

    if (mouse_areas.length <= 0)
        return false;

    for (_nr = 0; _nr < mouse_areas.length; _nr++) {

      	// ignore non-active mouse areas
      	if (!mouse_areas[_nr][6])
      	    continue;
      	
      	mouse_areas[_nr][ 6] = 0;                   // set status off
      	mouse_areas[_nr][11](mouse_areas[_nr][12]); // trigger off function call

    }
}

/*
** FUNCTION
**     __hook_mouse_move(e)
**
** COMMENTS
**     called from the main document, when a mousemove event is triggered.
*/

function __hook_mouse_move(e) {

    xMousePos = 0;   // main documents x position
    yMousePos = 0;   // main documents y position
    __xMousePos = 0; // x position related to 'main' divs scroll modifier
    __yMousePos = 0; // y position related to 'main' divs scroll modifier

    e = (e ? e : window.event); // works on IE, but not NS (we rely on NS passing us the event)

    if (e) {
   
        if (e.clientX || e.clientY) { // works on IE6,FF,Moz,Opera7
            xMousePos = e.clientX + document.body.scrollLeft;
            yMousePos = e.clientY + document.body.scrollTop;
            /*
            if ((__tmp_target = query_object("main"))) {
                __xMousePos = e.clientX + __tmp_target.scrollLeft;
                __yMousePos = e.clientY + __tmp_target.scrollTop;
            }
            */
            __xMousePos = e.clientX + document.scrollLeft;
            __yMousePos = e.clientY + document.scrollTop;
        }
        
        else if (e.pageX || e.pageY) { // this doesn't work on IE6!! (works on FF,Moz,Opera7)
            xMousePos = e.pageX;
            yMousePos = e.pageY;
            __xMousePos = e.pageX;
            __yMousePos = e.pageY;
        }
        
    }  

    window.status = "x: " + xMousePos + "(" + __xMousePos + "), y: " + yMousePos + "(" + __yMousePos + "), max_y: " + pageHeight() + ", diff (max_y - y): " + (pageHeight() - __yMousePos);

    // check all registered mouse areas
    __check_all_areas();

    // attempt call active elements '__hook_mouse_moving()' if any
    try { __hook_mouse_moving(); }
   	catch(err) { } // ignore non existing function, no error msg!
}

function query_mouse_x() {
    return xMousePos;
}

function query_mouse_y() {
    return yMousePos;
}

function __query_mouse_x() {
    return __xMousePos;
}

function __query_mouse_y() {
    return __yMousePos;
}

/*
** FUNCTION
**     __show_mouse_areas()
**
** COMMENTS
**     you can use this function to "reveal" registered mouse areas.
**
** NOTE
**     this function is ment for debugging only!
*/

function __show_mouse_areas() {
    var _nr;
    
    if (mouse_areas.length <= 0 || !(target = query_object("main"))) // 'main' is name of area element where you put your HTML
        return false;
    
    for (_nr = 0; _nr < mouse_areas.length; _nr++) {

        _x1 = mouse_areas[_nr][ 1];
        _y1 = mouse_areas[_nr][ 2];
        _x2 = mouse_areas[_nr][ 3];
        _y2 = mouse_areas[_nr][ 4];
        _f1 = mouse_areas[_nr][ 5];

        _x3 = mouse_areas[_nr][ 7];
        _y3 = mouse_areas[_nr][ 8];
        _x4 = mouse_areas[_nr][ 9];
        _y4 = mouse_areas[_nr][10];
        _f2 = mouse_areas[_nr][11];

        // check for max_y string in y1
        if (typeof(_y1) == "string" && _y1.indexOf("max_y") > -1) {
            _val = pageHeight();
            _y1 = _y1.replace("max_y", ""); // remove 'maxy' reference tag from string
            _val += parseInt(_y1); // add remaining value modifier ("+20", "-20") etc
            _y1 = _val;
        }
        // check for max_y string in y2
        if (typeof(_y2) == "string" && _y2.indexOf("max_y") > -1) {
            _val = pageHeight();
            _y2 = _y2.replace("max_y", ""); // remove 'maxy' reference tag from string
            _val += parseInt(_y2); // add remaining value modifier ("+20", "-20") etc
            _y2 = _val;
        }
        
        // check for max_y string in y3
        if (typeof(_y3) == "string" && _y3.indexOf("max_y") > -1) {
            _val = pageHeight();
            _y3 = _y3.replace("max_y", ""); // remove 'maxy' reference tag from string
            _val += parseInt(_y3); // add remaining value modifier ("+20", "-20") etc
            _y3 = _val;
        }
        // check for max_y string in y4
        if (typeof(_y4) == "string" && _y4.indexOf("max_y") > -1) {
            _val = pageHeight();
            _y4 = _y4.replace("max_y", ""); // remove 'maxy' reference tag from string
            _val += parseInt(_y4); // add remaining value modifier ("+20", "-20") etc
            _y4 = _val;
        }

        // check for center string in y1
        if (typeof(_y1) == "string" && _y1.indexOf("center") > -1) {
            _val = pageHeight() / 2;
            _y1 = _y1.replace("center", ""); // remove 'maxy' reference tag from string
            _val += parseInt(_y1); // add remaining value modifier ("+20", "-20") etc
            _y1 = _val;
        }
        // check for center string in y2
        if (typeof(_y2) == "string" && _y2.indexOf("center") > -1) {
            _val = pageHeight() / 2;
            _y2 = _y2.replace("center", ""); // remove 'maxy' reference tag from string
            _val += parseInt(_y2); // add remaining value modifier ("+20", "-20") etc
            _y2 = _val;
        }
        
        // check for center string in y3
        if (typeof(_y3) == "string" && _y3.indexOf("center") > -1) {
            _val = pageHeight() / 2;
            _y3 = _y3.replace("center", ""); // remove 'maxy' reference tag from string
            _val += parseInt(_y3); // add remaining value modifier ("+20", "-20") etc
            _y3 = _val;
        }
        // check for center string in y4
        if (typeof(_y4) == "string" && _y4.indexOf("center") > -1) {
            _val = pageHeight() / 2;
            _y4 = _y4.replace("center", ""); // remove 'maxy' reference tag from string
            _val += parseInt(_y4); // add remaining value modifier ("+20", "-20") etc
            _y4 = _val;
        }

    	target.innerHTML += "<div style='border-style:solid; border-color:#ffffff; border-size:1px; position:absolute; width:"+(parseInt(_x2) - parseInt(_x1))+"px; height:"+(parseInt(_y2) - parseInt(_y1))+"px; left:"+_x1+"px; top:"+_y1+"px;'></div>";    	
    }

    return -1;
}