//var _gaq = null;
var utils = {
    //ham lay doi tuong phat sinh event,
    getElementFireEvent: function(e) {
        e = e || window.event;
        return Event.element(e);
    },

    /* ham so sanh 2 chuoi,
    * return true neu 2 str giong hau,
    * false neu 2 str khac nhau
    */
    compare2String: function(str1, str2) {
        if (str1 == null || str2 == null) {
            return false;
        }
        else if (str1 == "" || str2 == "") {
            return false;
        }
        else if (str1 == str2)
            return true;
        else
            return false;
    },

    /* ham so sanh chuoi voi regular expression,
    * return true neu str thoa dieu kien cua regex,
    * false neu str khong thoa dieu kien cua regex
    */
    compareStr2Regex: function(str, regex) {
        if (regex.test(str))
            return true;
        else
            return false;
    },

    //ham tao obj XMLHTTPRequest goi tu thu vien Prototype.js
    createXMLHTTPRequest: function() {
        return Ajax.getTransport;
    },

    /* ham load file xml tu url duoc cung cap
    * url: path cua file xml
    *handleFunction: ten cua ham xu ly khi file xml duoc load ve
    * ham tra ve doi tuong xml neu load thanh cong
    * tra ve string 'false' neu load that bai sau 10 giay
    */
    loadXMLFile: function(url, handleFunction) {
        var myAjax = new Ajax.Request(
			url,
			{
			    method: 'get',
			    requestTimeout: 10,
			    onSuccess: function(response) {
			        handleFunction(response);
			    },
			    onTimeout: function() {
			        handleFunction('false');
			    }
			}
        );
    },

    /*fix transparent cho cac image 
    * divId la mot ID: fix cho cac obj trong div do 
    * divId = '' : fix cho toan bo trang web
    *shim: path den file gif trang 1x1 px, sua lai cho phu hop
    */
    fixPNGForIE6: function(divId) {
        var version = parseFloat(navigator.appVersion.split('MSIE')[1]);
        if ((version >= 5.5) && (version < 7) && (document.body.filters)) {

            // Path to a transparent GIF image
            var shim = '../images/spacer.gif';
            // RegExp to match above GIF image name
            //var shim_pattern	= /spacer\.gif$/i;
            var applyPositioning = true;

            var root;
            if (divId != "") {
                root = $(divId);
            } else {
                root = document;
            }
            for (var i = root.all.length - 1, obj = null; (obj = root.all[i]); i--) {
                // background pngs
                if (obj.currentStyle && obj.currentStyle.backgroundImage.match(/\.png/i) !== null) {
                    var mode = 'scale';
                    var bg = obj.currentStyle.backgroundImage;
                    var src = bg.substring(5, bg.length - 2);
                    if (obj.currentStyle.backgroundRepeat == 'no-repeat') {
                        mode = 'crop';
                    }
                    obj.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='" + mode + "')";
                    obj.style.backgroundImage = 'url(' + shim + ')';
                }
                // image elements
                if (obj.tagName == 'IMG' && obj.src.match(/\.png$/i) !== null) {
                    var src = obj.src;
                    obj.style.width = obj.width + "px";
                    obj.style.height = obj.height + "px";
                    obj.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='scale')";
                    obj.src = shim;
                }
                // apply position to 'active' elements
                if (applyPositioning && (obj.tagName == 'A' || obj.tagName == 'INPUT') && obj.style.position === '') {
                    obj.style.position = 'relative';
                }
            }
        }
    },

    //ham lay vi tri mouse tren man hinh khi click
    getMousePosOnScreen: function(e) {
        e = e || window.event;
        return [Event.pointerX(e), Event.pointerY(e)];
    },

    //ham lay vi tri mouse tren element duoc click
    getMousePosOnElement: function(e) {
        if ('undefined' == typeof e) {
            e = window.event;
            var x = e.offsetX;
            var y = e.offsetY;
        }
        else {
            var d = this.getElementFireEvent(e);
            var l = d.offsetLeft;
            var t = d.offsetTop;
            var x = e.clientX - l;
            var y = e.clientY - t;
        }
        return [x, y];
    },

    //ham tao string ngau nhien co chieu dai duoc chi dinh trong tham so length
    random: function(length) {
        var arrLetters = ["a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F", "g", "G", "h", "H", "i", "I", "j", "J", "k", "K", "l", "L", "m", "M", "n", "N", "o", "O", "p", "P", "q", "Q", "r", "R", "z", "Z", "t", "T", "u", "U", "v", "V", "w", "W", "x", "X", "y", "Y", "z", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
        var returnString = "";
        for (var i = 0; i < length; i++) {
            var iTmp = Math.floor(Math.random() * 62);
            returnString += arrLetters[iTmp];
        }
        arrLetters = null;
        return returnString;
    },

    //convert char to byte
    charToByte: function(character) {
        var i, num = charArray.length;
        for (var i = 0; i < num; i++) {
            if (character == charArray[i])
                return i + 32;
        }
        charArray = null;
        return 0;
    },

    //convert byte to char
    byteToChar: function(n) {
        if (n < 32 || n > 255)
            return " ";
        return charArray[n - 32];
    },
    //convert byte To Hex
    byteToHex: function(n) {
        var hex_digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
        return hex_digits[(n >> 4) & 0xf] + hex_digits[n & 0xf];
    }, //byte to binary
    byteToBin: function(n) {
        var ret_str = ""; var i;
        for (i = 7; i >= 0; i--) {
            ret_str += (n >> i) & 1;
        }
        return ret_str;
    }, // chuyen sang decimal
    from_dec: function(value) {
        var hex_dec, charhex;
        hex_dec = this.hex_from_dec(value);
        return hex_dec;
    }, // chuyen sang binary tu so hex
    from_char: function(value) {
        var hex = this.hex_from_chars(value);
        var chars, bin;
        bin = this.bin_from_hex(hex);
        chars = this.dec_from_hex(hex);
        return chars;
    },
    hex_from_chars: function(value) {
        var char_str = value; var hex_str = "";
        var i, n;
        for (i = 0; i < char_str.length; i++) {
            n = this.charToByte(char_str.charAt(i));
            if (n != 0) {
                hex_str += this.byteToHex(n);
            }
        }
        return hex_str;
    },
    //--------------------------------------
    dec_from_hex: function(value) {
        var hex_str = this.clean_numstr(value, 16);
        var dec_str = "";
        var dec_byte = "";
        var i;
        for (i = 0; i < hex_str.length - 1; i += 2) {
            dec_str += parseInt(hex_str.substring(i, i + 2), 16);
        }
        return dec_str;
    },
    //-----------------------------
    chars_from_hex: function(value) {
        var hex_str = clean_numstr(value, 16);
        var char_str = "";
        var num_str = "";
        var i;
        for (i = 0; i < hex_str.length; i += 2)
            char_str += this.byteToChar(parseInt(hex_str.substring(i, i + 2), 16));
        return char_str;
    },
    //--------------------------
    hex_from_dec: function(value) {
        var dec_str = this.clean_numstr(value, 10);
        var hex_str = ""; var num_str = ""; var i = 0, n;
        while (i < dec_str.length) {
            n = 0;
            for (; i < dec_str.length && (n < 25 || (n == 25 && dec_str.charAt(i) < 6)); i++) {
                n *= 10;
                n += parseInt(dec_str.charAt(i));
            }
            hex_str += this.byteToHex(n);
        }
        return hex_str; //isNothing(hex_str, value, "value = str");
    },
    bin_from_hex: function(value) {
        var hex_str = this.clean_numstr(value, 16);
        var bin_str = ""; var bin_byte = "";
        var i;
        for (i = 0; i < hex_str.length - 1; i += 2) {
            bin_str += this.byteToBin(parseInt(hex_str.substring(i, i + 2), 16));
        }
        return bin_str;
    },
    clean_numstr: function(raw_str, base) {
        var ret_str = ""; var c = "";
        var i;
        for (i = 0; i < raw_str.length; i++) {
            c = raw_str.charAt(i);
            if (c == "0" || parseInt(c, base) > 0) {
                ret_str += c;
            }
        }
        return ret_str;
    }, // ham ma hoa,msg: chuoi can ma hoa, P: pass de ma hoa, neu truyen ko du thong so, se la gia tri P mac dinh
    encode: function(msg, P) {
        /*if(arguments.length==1) {
        if(strCode2Pass.indexOf("4map")==-1 )P=strCode2Pass+"4map";
        else P=strCode2Pass;
        }else P=strCode2Pass;
        if(P=='') P=mkey;*/
        var E = "", b = '';
        var i = 0, j, k, A2, A3, A, p = '';
        A = '';
        try {
            for (i = 0; i <= P.length - 1; i++) {
                p += this.from_char(P.substring(i, i + 1));
            }
            j = 1;
            for (k = 0; k <= msg.length - 1; k++) {
                A = this.from_char(p.substring(j, j + 1));
                j++;
                if (j >= p.length) j = 1;
                A2 = this.from_char(msg.substring(k, k + 1));
                A3 = (A ^ A2).toString();
                b = this.from_dec(A3);

                if (b.toString().length < 2) { b = "0" + b; }
                E += b;
            }
        }
        //edit 26/08/2009  
        catch (e) { }
        return E;
    },
    decode: function(msg, strp) {
        var p, j, A3, A2, A1;
        /* if(arguments.length==1) {
        if(strCode2Pass.indexOf("4map")==-1 ) {strp=strCode2Pass+"4map";}
        else{ strp=strCode2Pass};
        }
        else strp=strCode2Pass;*/
        var D = '', P = '', b = '';
        try {
            for (var i = 0; i <= strp.length - 1; i++) { p = utils.from_char(strp.substring(i, i + 1)); P += p; }
            j = 1;
            for (var i = 0; i <= msg.length - 1; i += 2) {
                A1 = this.from_char(P.substring(j, j + 1));

                j++; if (j >= P.length) j = 1;
                b = msg.substring(i, i + 2);
                A3 = this.dec_from_hex(b);
                A2 = A1 ^ A3;
                D += String.fromCharCode(A2);
            }
        }
        catch (ex) { D = ''; }
        return D;
    }, //------------	 ham ma hoa don gian 
    codeEn: function(str, pas) {
        if (arguments.length == 1) P = strCode2Pass + "4map";
        var p = 0, k = 0; s = '', r = 0;
        for (var i = 0; i < pas.length; i++) p += parseInt(this.from_char(pas.substr(i, 1)));
        p += '';
        for (var j = 0; j < str.length; j++) {
            r = parseInt(this.from_char(str.substr(j, 1)));
            if (k == p.length) k = 0;
            r += parseInt(p.substr(k, 1));
            k++;
            s += escape(r + '%20');
        }
        return unescape(s);
    },
    codeDe: function(str, pas) {
        if (arguments.length == 1) P = strCode2Pass + "4map";
        str = trim(unescape(str)).split(' ');
        var p = 0, k = 0;
        var s = '', r = 0;
        for (var i = 0; i < pas.length; i++) p += parseInt(this.from_char(pas.substr(i, 1)));
        p += '';
        for (var j = 0; j < str.length; j++) {
            r = parseInt(str[j]);
            if (k == p.length) k = 0;
            r -= parseInt(p.substr(k, 1));
            k++;
            s += String.fromCharCode(escape(r));
        }
        return s;
    },
    // this function use test IE, firefox if return -1:IE else return 0: Firefox
    IE_Firefox: function() {
        //debugger;
        return (navigator.appName.indexOf('Netscape') >= 0 || navigator.appName.indexOf('Opera') >= 0) ? 0 : -1;
    },
    // this function use test IE6, IE7, firefox, if return -1: firefox, 6:IE6, 7: IE7
    IE7_Firefox: function() {
        return (navigator.appName == 'Microsoft Internet Explorer') ? parseFloat((new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})")).exec(navigator.userAgent)[1]) : -1;
    },
    IE6_Else: function() { // neu ie7,ff, return true, else return  false;
        if (typeof document.body.style.maxHeight != "undefined") return true; // ie7, firefox
        return false;
    },

    Safari: function() {
        var str = ''; // ie6:0,ie7:1,firefox:2
        var strReturn = -1;
        if (navigator.userAgent.toString() != '') { //  Ie, mozilla, OmniWeb,firefox,netscape ; gia tri tu -1=>5
            str = navigator.userAgent.toString().toUpperCase();
            if (str.indexOf("SAFARI") != -1) strReturn = 5; // safari
        }
        return strReturn;
    },

    // get version of window
    version: function() {
        var str = "";
        str = navigator.userAgent.toString().toUpperCase();
        return str;
    },

    // this function check number if object is numeric return true else return false;
    isNumeric: function(object) {
        return object.length ? !isNaN(object.replace(/\s/, "z") / 1) : true;
    },

    // this function check mail if object is email return true else return false;
    checkMail: function(object) {
        var sQtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
        var sDtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
        var sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
        var sQuotedPair = '\\x5c[\\x00-\\x7f]';
        var sDomainLiteral = '\\x5b(' + sDtext + '|' + sQuotedPair + ')*\\x5d';
        var sQuotedString = '\\x22(' + sQtext + '|' + sQuotedPair + ')*\\x22';
        var sDomain_ref = sAtom;
        var sSubDomain = '(' + sDomain_ref + '|' + sDomainLiteral + ')';
        var sWord = '(' + sAtom + '|' + sQuotedString + ')';
        var sDomain = sSubDomain + '(\\x2e' + sSubDomain + ')*';
        var sLocalPart = sWord + '(\\x2e' + sWord + ')*';
        var sAddrSpec = sLocalPart + '\\x40' + sDomain; // complete RFC822 email address spec
        var sValidEmail = '^' + sAddrSpec + '$'; // as whole string

        var reValidEmail = new RegExp(sValidEmail);

        if (reValidEmail.test(object)) {
            return true;
        }
        return false;
    },

    // this function is trim space in string, return a string; 	
    trim: function(object) {
        if (object == "") return object;
        return object.replace(/^\s*|\s*$/g, "");
    },

    delSubString: function(delStr, mainStr) {
        var strReturn = mainStr;
        if (mainStr.indexOf(delStr) != -1) {
            strReturn = '';
            mainStr = mainStr.split(delStr);
            strReturn = mainStr.join("");
        }
        return strReturn;
    },

    // this function using delete px in last number, return number;
    rejectUnit: function(element) {
        var strpx = /px/i;
        element = element.toString();
        if (element.search(strpx) != -1) {
            return parseInt(element.substring(0, element.length - 2)); /*Quang 06/08*/
        }
        return parseInt(element);
    },

    // this function using to get width and height of Scroll	
    windowScroll: function() {
        var myScrollWidth = document.all ? Math.max(Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth), document.body.scrollWidth) : (document.body ? document.body.scrollWidth : ((document.documentElement.scrollWidth != 0) ? document.documentElement.scrollWidth : 0));
        var myScrollHeigh = document.all ? Math.max(Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight), Math.max(document.body.offsetHeight, document.body.scrollHeight)) : (document.body ? document.body.scrollHeight : ((document.documentElement.scrollHeight != 0) ? document.documentElement.scrollHeight : 0));
        return [myScrollWidth, myScrollHeigh];
    },

    // this function using to get width and height of window size
    windowSize: function() {
        var iMyWidth = 0, iMyHeight = 0;
        if (typeof (window.innerWidth) == 'number') {
            //Non-IE
            iMyWidth = window.innerWidth;
            iMyHeight = window.innerHeight;
        } else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
            //IE 6+ in 'standards compliant mode'
            iMyWidth = document.documentElement.clientWidth;
            iMyHeight = document.documentElement.clientHeight;
        } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
            //IE 4 compatible
            iMyWidth = document.body.clientWidth;
            iMyHeight = document.body.clientHeight;
        }
        return [iMyWidth, iMyHeight];
    },
    TopLeftWindow: function(element) {

        var id = $(element);
        var curLeft = 0;
        var curTop = 0;
        if (id.offsetParent) {
            do {
                curLeft += parseInt(id.offsetLeft);
                curTop += parseInt(id.offsetTop);
            } while (id = id.offsetParent);
        }
        return [curLeft, curTop];
    },
    getDDLIndex: function(obj, value) {
        if (typeof (obj) == "string") {
            //obj la string chua id ddl
            obj = $(obj);
        }
        else if (typeof (obj) != "object") {
            //obj khong hop le
            return -2;
        }
        value = value.toUpperCase();
        var arrTmp = obj.options;
        for (var i = arrTmp.length - 1; i >= 0; i--) {
            if (arrTmp[i].value.toUpperCase() == value)
                return i;
        }
        return -1;
    },
    getCursorPos: function(e) //lay vi tri con tro
    {
        var pcursor = { x: 0, y: 0 };
        e = e || window.event;
        if (e.pageX || e.pageY) {
            pcursor.x = e.pageX;
            pcursor.y = e.pageY;
        }
        else {
            var de = document.documentElement;
            var db = document.body;
            pcursor.x = e.clientX +
            (de.scrollLeft || db.scrollLeft) - (de.clientLeft || 0);
            pcursor.y = e.clientY +
            (de.scrollTop || db.scrollTop) - (de.clientTop || 0);
        }
        return pcursor;
    },
    selectElement: function(element) {
        if (document.selection) {
            var range = document.body.createTextRange();
            range.moveToElementText(element);
            range.select();
        }
        else if (window.getSelection) {
            var range = document.createRange();
            range.selectNodeContents(element);
            var selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
        }
    },
    newElementClassName: function(typeOfElm, idElm, classNameElm) {
        var newElement = document.createElement(typeOfElm);
        newElement.id = idElm;
        newElement.className = classNameElm;
        return newElement;
    }, // tao element moi 
    createNewElement: function(typeOfElm, idElm, posElm, topElm, bottomElm, leftElm, rightElm, heightElm, widthElm, zindex, bgColorEml, fontWeightElm, colorElm, emDisplay) {
        var newElement = document.createElement(typeOfElm);
        newElement.id = idElm;
        newElement.style.position = posElm;
        if (topElm != -1) newElement.style.top = topElm + "px";
        if (bottomElm != -1) newElement.style.bottom = bottomElm + "px";
        if (leftElm != -1) newElement.style.left = leftElm + "px";
        if (rightElm != -1) newElement.style.right = rightElm + "px";
        if (heightElm != -1) newElement.style.height = heightElm + "px";
        if (widthElm != -1) newElement.style.width = widthElm + "px";
        if (zindex != -1) newElement.style.zIndex = zindex;
        if (bgColorEml != -1) newElement.style.backgroundColor = bgColorEml;
        if (fontWeightElm != -1) newElement.style.fontWeight = fontWeightElm;
        if (colorElm != -1) newElement.style.color = colorElm;
        if (emDisplay != -1) newElement.style.display = emDisplay;
        return newElement;
    },
    RegNum: function(numToTest) {
        var t = numToTest + "";
        var r = /^-{0,1}\d*\.{0,1}\d+$/i; ///^-\d*\.{0,1}\d+$/i  ;
        if (t.match(r)) return true;
        return false;
    },
    sortNumber: function(a, b) {
        return parseInt(a) - parseInt(b);
    },
    toProperCase: function(s) {
        return s.toLowerCase().replace(/^(.)|\s(.)/g,
          function($1) { return $1.toUpperCase(); });
    }, // xem 3 diem nay co nam gap khuc khong 
    triPointCenter: function(x1, x2, x3) {
        x1 = parseFloat(x1); x2 = parseFloat(x2); x3 = parseFloat(x3);
        if (((x1 < x2) && (x2 > x3)) || ((x1 > x2) && (x2 < x3))) return true;
        return false;
    }, // neu goc <=45 return true, else return false;
    acuteAngle: function(x1, x2, x3, y1, y2, y3) { // 2 duong thang x1,x2 va x2,x3
        var a = y1 - y2;
        var a1 = y2 - y3;
        var b = x2 - x1;
        var b1 = x3 - x2;
        var strValue = Math.acos((a * a1 + b * b1) / Math.sqrt((a * a + b * b) * (a1 * a1 + b1 * b1))) / Math.PI;
        return (strValue < 0.8 & strValue > -0.8) ? false : true;
    },
    call: function(url, param, mthod, fncSucess, fncFailure) {

        oJax = new Ajax.Request(url, {

            method: mthod,
            parameters: param,
            onSuccess: function(transport) {

                var response = transport.responseText;
                if (utils.trim(response).length > 0) {
                    try {

                        eval(fncSucess + "(" + response + ");");
                    } catch (ex) { eval(fncSucess + "('" + response + "');"); }
                } else {
                    eval(fncSucess + "('" + response + "');");
                }
            },
            //onException:function(wx){ debugger; alert(wx.toString());},
            onFailure: function(transport) {
                eval(fncFailure('" +response+"'));
            }
        }
        );
        if (url.toLowerCase() != "suggestion.aspx" && url.toLowerCase() != "../signin.aspx" && url.toLowerCase() != "signin.aspx" && _gaq != null && _gaq != undefined) {
            _gaq.push(['_trackPageview', url]);
        }
    }, // lay ve width & height cua 1 image khi image duoc ga'n dong
    imageSize: function(path) {
        var widthImg = 0, heightImg = 0;
        var objImg = new Image();
        objImg.src = path;
        objImg.onload = function() {
            widthImg = objImg.width; heightImg = objImg.height;
        };
        widthImg = (widthImg != 0) ? widthImg : objImg.width;
        heightImg = (heightImg != 0) ? heightImg : objImg.height;
        return [widthImg, heightImg];
    },
    crssDomain: function(Id) {
        var script = document.createElement("script");
        script.setAttribute("id", Id);
        script.setAttribute("type", "text/javascript");
        document.body.appendChild(script);
    },
    activeURL: function(id, url) {
        try {
            if ((utils.IE7_Firefox() == -1) | this.Safari() == 5) {
                if ($(id)) { $(id).remove(); this.crssDomain(id); $(id).setAttribute("src", url); }
            }
            else { if ($(id)) $(id).setAttribute("src", url); }
            //edit 26/08/2009         
        } catch (ex) { }
    },
    replaceString: function(parStr, subStr, str) {
        while (parStr.indexOf(subStr) != -1) {
            parStr = parStr.replace(subStr, str);
        }
        return parStr;
    },
    parse2Query: function(str) {
        var param = [];
        str = str.substring(1);
        var p = str.split("&");
        for (var i = 0; i < p.length; i++)
            param[i] = p[i].split("=")[1];
        return param;
    }, //edit 26/08/2009
    stateName: function(areaCode) {
        switch (areaCode) {
            case "8":
                return "saigon";
            case "4":
                return "hanoi";
            case "710":
                return "cantho";
            case "64":
                return "vungtau";
            case "31":
                return "haiphong";
            case "37":
                return "thanhhoa";
            case "511":
                return "danang";
            case "52":
                return "donghoi";
            case "54":
                return "hue";
            case "58":
                return "nhatrang";
            case "61":
                return "dongnai";
            case "62":
                return "binhthuan";
            case "650":
                return "binhduong";
            case "68":
                return "ninhthuan";
        }

    }
};
/**************************************************
* dom-drag.js
* 09.25.2001
* www.youngpup.net
* Script featured on Dynamic Drive (http://www.dynamicdrive.com) 12.08.2005
**************************************************
* 10.28.2001 - fixed minor bug where events
* sometimes fired off the handle, not the root.
**************************************************/
var Drag = {
    obj: null,
    init: function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) {
        o.onmousedown = Drag.start;
        o.hmode = bSwapHorzRef ? false : true;
        o.vmode = bSwapVertRef ? false : true;
        o.root = oRoot && oRoot != null ? oRoot : o;
        if (o.hmode && isNaN(parseInt(o.root.style.left))) o.root.style.left = "0px";
        if (o.vmode && isNaN(parseInt(o.root.style.top))) o.root.style.top = "0px";
        if (!o.hmode && isNaN(parseInt(o.root.style.right))) o.root.style.right = "0px";
        if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
        o.minX = typeof minX != 'undefined' ? minX : null;
        o.minY = typeof minY != 'undefined' ? minY : null;
        o.maxX = typeof maxX != 'undefined' ? maxX : null;
        o.maxY = typeof maxY != 'undefined' ? maxY : null;
        o.xMapper = fXMapper ? fXMapper : null;
        o.yMapper = fYMapper ? fYMapper : null;
        o.root.onDragStart = new Function();
        o.root.onDragEnd = new Function();
        o.root.onDrag = new Function();
    },
    start: function(e) {
        var o = Drag.obj = this;
        e = Drag.fixE(e);
        var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
        var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right);
        o.root.onDragStart(x, y);
        o.lastMouseX = e.clientX;
        o.lastMouseY = e.clientY;
        if (o.hmode) {
            if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;
            if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;
        } else {
            if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
            if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
        }
        if (o.vmode) {
            if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;
            if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;
        } else {
            if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
            if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
        }
        document.onmousemove = Drag.drag;
        document.onmouseup = Drag.end;
        return false;
    },
    drag: function(e) {
        e = Drag.fixE(e);
        var o = Drag.obj;
        var ey = e.clientY;
        var ex = e.clientX;
        var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
        var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right);
        var nx, ny;
        if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
        if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
        if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
        if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);
        nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
        ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
        if (o.xMapper) nx = o.xMapper(y);
        else if (o.yMapper) ny = o.yMapper(x);
        Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
        Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
        Drag.obj.lastMouseX = ex;
        Drag.obj.lastMouseY = ey;
        Drag.obj.root.onDrag(nx, ny);
        return false;
    },
    end: function() {
        document.onmousemove = null;
        document.onmouseup = null;
        Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]),
									parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
        Drag.obj = null;
    },
    fixE: function(e) {
        if (typeof e == 'undefined') e = window.event;
        if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
        if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
        return e;
    }
};

