﻿(function(){    // 单调方法，隐藏内部变量和方法
/***************************** 预载 *****************************/
/// 图片预加载
// img  一张或多张图片的地址
window.preLoadImage = function(/*Url|Url[]*/ img)
{
    if (!img)
    {
        return;
    }
    if (typeof img == "string")
    {
        (new Image()).src = img;
        return;
    }
    if (img.length)
    {
        for (var i = 0, l = img.length; i < l; i++)
        {
            (new Image()).src = img[i];
        }
    }
};
preLoadImage([
                // Tooltip
                "/JsLib/20090331/Images/tooltipConnectorRight.gif",
                "/JsLib/20090331/Images/tooltipConnectorLeft.gif",
                "/JsLib/20090331/Images/tooltipbg.jpg",
                "/JsLib/20090331/Images/tooltipclose.gif",
                // Dialog
                "/JsLib/20090331/Images/dialog_bar_bg.jpg",     
                "/JsLib/20090331/Images/dialog_close.gif",
                "/JsLib/20090331/Images/popBtnbg.gif",
                // Map
                "/JsLib/20090331/Images/mappop-top.gif",
                "/JsLib/20090331/Images/mappop-top-s.gif",
                "/JsLib/20090331/Images/mappop-right.gif",
                "/JsLib/20090331/Images/mappop-btm.gif",
                "/JsLib/20090331/Images/mappop-btm-s.gif",
                "/JsLib/20090331/Images/mappop-arrow.gif",
                "/JsLib/20090331/Images/icon-pao1.gif",
                "/JsLib/20090331/Images/icon-pao2.gif",
                "/JsLib/20090331/Images/icon-pao3.gif",
                "/JsLib/20090331/Images/btn-bg.gif",
                // TooltipControl
                "/FamilyNew/Home/Images/module_top.jpg",
                "/FamilyNew/Home/Images/icon-pop.gif",
                "/FamilyNew/Home/Images/contentbg.jpg",
                "/FamilyNew/Home/Images/icon-call.gif",
                "/FamilyNew/Home/Images/icon-addfriend.gif",
                "/FamilyNew/Home/Images/btn-close.gif"
            ]);
/***************************** 基础类扩展 *****************************/
/****** String ******/
/// 返回字符串的字节长度
// text     字符串
window.byteLength = function(/*String*/ text)
{
    var length = 0;
    if (typeof text == 'string' || text instanceof String)
    {
        for (var i = 0, l = text.length; i < l; i++)
        {
            var charCode = text.charCodeAt(i);
            length += ((charCode > 255 || charCode == 183) ? 2 : 1);
        }
    }
    return length; // int
};
/// 从字符串中截取指定字节长度的子字符串，并加指定后缀
// text     字符串
// length   需截取的字节长度
// suffix   可选，后缀，默认为"..."
window.subString = function(/*String*/ text, /*int*/ length, /*String?*/ suffix)
{
    if (byteLength(text) <= length)
    {
        return text;
    }
    if (!suffix && suffix !== "")
    {
        suffix = "...";
    }
    var str = "";
    var count = byteLength(suffix);
    for(var i = 0; count < length; i++)
    {
        var schar = text.charAt(i);
        str += schar;
        count += byteLength(schar);
    }
    str += suffix;
    return str; // String
};
/// 从字符串中截取指定字节长度的子字符串，不加后缀
// text     字符串
// length   需截取的字节长度
window.cutString = function(text, length)
{
    return subString(text, length, ""); // String
};
/// 去掉字符串中的标签，返回纯文本
// text     带标签的字符串，Html Xml 等
window.stripTags = function(/*Html|Xml*/ text)
{
    return text.replace(/<\/?[^>]+>/gi, ""); // String
};
/// Html编码
// text     字符串
window.htmlEncode = function(/*String*/ text)
{
    return text.replace(/&/g, '&amp;').replace(/ /g, '&nbsp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;'); // String
};
/// Html解码
// text     字符串
window.htmlDecode = function(/*String*/ text)
{
    return text.replace(/&nbsp;/g, ' ').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&').replace(/&quot;/g, '\"'); // String
};

/****** Array ******/
if (!Array.prototype.copy) {
/// 复制数组
Array.prototype.copy = function()
{
    return this.concat(); // Array
}}
if (!Array.prototype.indexOf) {
/// 在数组中从指定位置开始，顺序查找，指定的值在该数组中第一次出现的位置，未找到返回 -1
// value        待查找的值
// startIndex   可选，查找的开始位置，默认为首位，如：2 表示数组的正数第三项，-2 表示数组的倒数第二项
Array.prototype.indexOf = function(/*Object*/ value, /*int?*/ startIndex)
{
    if (!startIndex && startIndex !== 0)
    {
        startIndex = 0;
    }
    else
    {
        if (startIndex < 0)
        {
            startIndex = Math.max(0, this.length + startIndex);
        }
    }
    for (var i = startIndex, l = this.length; i < l; i++)
    {
        if (this[i] === value)
        {
            return i; // int
        }
    }
    return -1; // int
}}
if (!Array.prototype.lastIndexOf) {
/// 在数组中从指定位置开始，倒序查找，指定的值在该数组中第一次出现的位置，未找到返回 -1
// value        待查找的值
// startIndex   可选，查找的开始位置，默认为末位，如：2 表示数组的正数第三项，-2 表示数组的倒数第二项
Array.prototype.lastIndexOf = function(/*Object*/ value, /*int?*/ startIndex)
{
    if (!startIndex && startIndex !== 0)
    {
        startIndex = this.length - 1;
    }
    else
    {
        if (startIndex < 0)
        {
            startIndex = Math.max(0, this.length + startIndex);
        }
    }
    for (var i = startIndex; i >= 0; i--)
    {
        if (this[i] === value)
        {
            return i; // int
        }
    }
    return -1; // int
}}
if (!Array.prototype.contains) {
/// 检测数组是否包含指定的值
// value    待查找的值
Array.prototype.contains = function(/*Object*/ value)
{
    return this.indexOf(value) != -1; // Boolean
}}
if (!Array.prototype.insertAt) {
/// 在数组的指定位置插入指定的值，其他项依次向后移一位
// index    数组中的位置，如：1 表示第二项
// value    待插入的值
Array.prototype.insertAt = function(/*int*/ index, /*Object*/ value)
{
    this.splice(index, 0, value);
}}
if (!Array.prototype.insertBefore) {
/// 在数组中的 valueInArray 之前插入指定的值 value，包括 valueInArray 在内的其他项依次向后移一位
/// 当 valueInArray 不在数组中时，则将 value 加到数组的最后
// value            待插入的值
// valueInArray     在数组中的某个值
Array.prototype.insertBefore = function(/*Object*/ value, /*Object*/ valueInArray)
{
    var index = this.indexOf(valueInArray); // 顺序查找 valueInArray 第一次出现的位置
    if (index == -1)
    {
        this.push(value);
    }
    else
    {
        this.splice(index, 0, value);
    }
}}
if (!Array.prototype.removeAt) {
/// 从数组中移出指定位置的项
// index    数组中的位置，如：1 表示第二项
Array.prototype.removeAt = function(/*int*/ index)
{
    this.splice(index, 1);
}}
if (!Array.prototype.remove) {
/// 从数组中移出指定值(只移出首次出现的项)
// value     在数组中的某个值
Array.prototype.remove = function(/*Object*/ value)
{
    var index = this.indexOf(value); // 顺序查找 value 第一次出现的位置
    if(index != -1)
    {
        this.splice(index, 1);
    }
}}



/****** Math ******/
if (!Math.randomInt) {
/// 获得随机整数
// max      可选，随机整数的最大值，默认为 10000，即返回 0-10000 之间的整数
Math.randomInt = function(/*int?*/ max)
{
    max = max || 10000;
    return Math.floor(Math.random() * (max + 1));   // int
}}

/***************************** 基础方法 *****************************/
/****** 反射方法 ******/
/// 是否未定义
// obj      检测的值
window.isUndefined = function(/*Object*/ obj)
{
    return typeof obj === 'undefined'; // Boolean
};
/// 是否为 null
// obj      检测的值
window.isNull = function(/*Object*/ obj)
{
    return obj === null; // Boolean
};
/// 是否为 String
// obj      检测的值
window.isString = function(/*Object*/ obj)
{
    return typeof obj === 'string'; // Boolean
};
/// 是否为 Number
// obj      检测的值
window.isNumber = function(/*Object*/ obj)
{
    return typeof obj === 'number' && isFinite(obj);
};
/// 是否为 Boolean
// obj      检测的值
window.isBoolean = function(/*Object*/ obj)
{
    return typeof obj === 'boolean'; // Boolean
};
/// 是否为 Array
// obj      检测的值
window.isArray = function(/*Object*/ obj)
{ 
    if (obj) 
    {
       return isNumber(obj.length) && isFunction(obj.splice);
    }
    return false; // Boolean
};
/// 是否为 Function
// obj      检测的值
window.isFunction = function(/*Object*/ obj)
{
    return typeof obj === 'function'; // Boolean
};
/****** 格式、编码转换 ******/
/*==数据格式定义==
QueryString     键值对组成的字符串，如： "id=128&name=John&birthday=1986-1-1"
Object          包含键值对的对象，如： {id: "128", name: "John", birthday: "1986-1-1"}
=====*/
/// QueryString 转换成 Object
// obj      键值对组成的字符串
window.queryToObject = function(/*String*/ queryString)
{
    var obj = {};
    var pairs = queryString.split("&");
    var regx = /([^=]*)=(.*)/;
    for (var i = 0, l = pairs.length; i < l; i++)
    {
        var matchs = regx.exec(pairs[i]);
        if (!matchs)
        {
            continue;
        }
        var key = decodeURIComponent(matchs[1]);
        var value = matchs[2] ? decodeURIComponent(matchs[2]) : undefined;
        if (typeof obj[key] != "undefined") // key 重复时，作为数组存放
        {
            if (!isArray(obj[key]))
            {
                obj[key] = [obj[key]];
            }
            if (value)
            {
                obj[key].push(value);
            }
        }
        else
        {
            obj[key] = value;
        }
    }
    return obj; // Object
};
/// Object 转换成 QueryString
// obj      包含键值对的对象
window.objectToQuery = function(/*Object*/ obj)
{
    var queryString = "";
    if (obj)
    {
        var isFirst = true;
        for (var key in obj)
        {
            var value = obj[key];
            if (isString(value) || isNumber(value) || isBoolean(value))
            {
                if (isFirst)
                {
                    isFirst = false;
                }
                else
                {
                    queryString += "&";
                }
                queryString += encodeURIComponent(key.toString()) + "=" + encodeURIComponent(value.toString());
            }
        }
    }
    obj = null;
    isFirst = null;
    key = null;
    value = null;
    return queryString; // String
};
/// TextArea 的 value 转换成 Html
// text     TextArea 的属性 value 的值
window.textAreaValueToHtml = function(/*String*/ text)
{
    return htmlEncode(text.toString()).replace(/\r\n/g, '<br/>'); // Html
};
/// Html 转换成 TextArea 的 value
// html     一段 Html
window.htmlToTextAreaValue = function(/*Html*/ html)
{
    return htmlDecode(html.toString().replace(/<br\x2F>/g, '\r\n')); // String
};
/*==数据格式定义==
DateString  表示日期，如: 2008-08-08
=====*/
/// DateString 转换成 Date
// dateString   日期字符串，数据格式见 DateString
window.dateStringToDate = function(/*DateString*/ dateString)
{
    if (isDateString(dateString))
    {
        var index = dateString.indexOf("-");
        var lastIndex = dateString.lastIndexOf("-");
        var year = dateString.substring(0, index);
        var month = dateString.substring(5, lastIndex);
        var day = dateString.substring(dateString.length, lastIndex + 1);
        var date = new Date(Date.parse(month + "/" + day + "/" + year));
        index = null;
        lastIndex = null;
        year = null;
        month = null;
        day = null;
        return date; // Date
    }
    else
    {
        return null; // null
    }
};
/// Date 转换成 DateString
// date   日期
window.dateToDateString = function(/*Date*/ date, p)
{
    if (date && typeof(date) == "object" && typeof(date.getFullYear) == "function")
    {
        var mMonth = (date.getMonth() + 1).toString();
        if (mMonth.length == 1)
        {
            mMonth = "0" + mMonth;
        }
        var mDay = date.getDate().toString();
        if (mDay.length == 1)
        {
            mDay = "0" + mDay;
        }
        return date.getFullYear() + "-" + mMonth + "-" + mDay; // DateString
    }
    else
    {
        return null; // null
    }
};
/*==数据格式定义==
PriceString  表示货币，如: 128.50
=====*/
/// Number 转换成 PriceString
window.numberToPriceString = function(/*Float*/ priceNumber)
{
    if (typeof(priceNumber) == "number" && !isNaN(priceNumber) && priceNumber >= 0)
    {
        var integralPart = Math.floor(priceNumber);
	    var fractionalPart = priceNumber - integralPart;
	    var firstPlace = Math.floor(fractionalPart * 10).toString();
	    var secondPlace = Math.floor((fractionalPart * 10 - firstPlace) * 10).toString();
	    return integralPart + "." + firstPlace + secondPlace; // String
    }
    else
    {
        return null; // null
    }
};
/****** 其它基础方法 ******/
/// 在对象上，增加或覆盖已有的属性或方法
// obj      目标对象
// props    具有新的属性、方法的对象
window.mixin = function(/*Object*/ obj, /*Object*/ props)
{
    if (!obj
        || (typeof(obj) != "object")
        || !props
        || (typeof(props) != "object"))
    {
        return obj; // Variant
    }
    var tobj = {};
    for (var x in props)
    {
        if (typeof tobj[x] == "undefined" || tobj[x] != props[x])
        {
            obj[x] = props[x];
        }
    }
    // 修正，toString在IE下被忽略的问题
    if (document.all && props)
    {
        var p = props.toString;
        if (typeof p == "function" 
            && p != obj.toString 
            && p != tobj.toString 
            && p != "\nfunction toString() {\n    [native code]\n}\n")
        {
            obj.toString = props.toString;
        }
    }
    return obj; // Object
};
var _isDateStringRegx = /(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)/;
/// 判断字符串的格式是否是 DateString，如: 2008-08-08
// dateString   待检查的字符串
window.isDateString = function(/*DateString*/ dateString)
{
    return !!(dateString && (typeof(dateString) == "string") && _isDateStringRegx.test(dateString)); // Boolean
};
/*==数据格式定义==
DateString  表示日期，如: 2008-08-08
=====*/
/// 比较日期字符串，返回相差的天数
/// DateString1 > DateString2 时，返回正整数
/// DateString1 == DateString2 时，返回 0
/// DateString1 < DateString2 时，返回负整数
// dateString1  日期字符串1，数据格式见 DateString
// dateString2  日期字符串2，数据格式见 DateString
window.compareDateString = function(/*DateString*/ dateString1, /*DateString*/ dateString2)
{
    if (isDateString(dateString1) && isDateString(dateString2))
    {
        return Math.floor((dateStringToDate(dateString1).getTime() - dateStringToDate(dateString2).getTime()) / 86400000); // int
    }
    else
    {
        return NaN; // NaN
    }
};

/***************************** 浏览器扩展 *****************************/
// API 报错
// message  错误信息
function __apiError(/*String*/ message)
{
    message = "API：" + message;
    alert(message);
    throw new Error(message);
};
var __userAgent   = navigator.userAgent.toLowerCase();
var __appVersion  = navigator.appVersion.toLowerCase();
var __isKhtml     = __appVersion.indexOf("konqueror") != -1 || __appVersion.indexOf("safari") != -1;
/// 检测浏览器类型
window.isOpera  = __userAgent.indexOf("opera") != -1;
window.isSafari = __userAgent.indexOf("safari") != -1;
window.isGecko  = !isOpera && !isSafari && __userAgent.indexOf("gecko") != -1;
window.isFF     = __userAgent.indexOf("gecko") != -1 && !__isKhtml && __userAgent.indexOf("firefox") != -1;
window.isIE     = !isOpera && __userAgent.indexOf("msie") != -1;
window.isIE6    = !isOpera && __userAgent.indexOf("msie 6") != -1;
window.isIE7    = !isOpera && __userAgent.indexOf("msie 7") != -1;
__userAgent = null;
__appVersion = null;
__isKhtml = null;
/// 回收内存
/// 注意: 
/// There is an undocumented JScript function called CollectGarbage that forces a garbage collection.
/// This is for testing purposes only—do not ship code that calls this function.
/// It is a poor programming practice to write code in JScript that depends on garbage collections being done at particular times.
/// If you need predictable garbage collection, use a language that supports it (like Visual Basic or VBScript).
/// Note that all of this is the implementation detail of the engine and should not be relied upon because it may change in the future. 
window.gc = function()
{
    if (isIE && isFunction(CollectGarbage))
    {
        CollectGarbage();
    }
};
/// 增加或覆盖指定 Cookie
// name     Cookie 名
// value    值
// hours    可选，有效期，单位：小时，默认为临时 Cookie，浏览器关闭后 Cookie 失效
// path     可选，路径，默认为"/"
// domain   可选，域，默认为当前域
// secure   可选，是否加密，默认为不加密
window.setCookie = function(/*String*/ name, /*String*/ value, /*int?*/ hours, /*String?*/ path, /*String?*/ domain, /*Boolean?*/ secure)
{
    var argv    = arguments;
    var argc    = arguments.length;
    var hours   = (argc > 2) ? argv[2]  : null;
    var path    = (argc > 3) ? argv[3]  : '/';
    var domain  = (argc > 4) ? argv[4]  : null;
    var secure  = (argc > 5) ? argv[5]  : false;
    var expdate = null;
    if (hours)
    {
        expdate = new Date(); 
        expdate.setTime(expdate.getTime() + hours * 3600000); 
    }
    var str = "";
    str += name.toString() + "=" + encodeURIComponent(value.toString());
    str += !expdate ? "" : ("; expires=" + expdate.toGMTString());
    str += !path    ? "" : ("; path=" + path);
    str += !domain  ? "" : ("; domain=" + domain);
    str += !secure  ? "" : ("; secure");
    document.cookie = str;
    argv = null;
    argc = null;
    hours = null;
    path = null;
    domain = null;
    secure = null;
    expdate = null;
    str = null;
};
/// 获得指定 Cookie
// name     Cookie 名
window.getCookie = function(/*String*/ name)
{
    var matchs = document.cookie.match("(?:^|;)\\s*" + name.toString() + "=([^;]*)");
    return matchs ? decodeURIComponent(matchs[1]) : "";
};
/// 删除指定 Cookie
// name     Cookie 名
window.removeCookie = function(/*String*/ name)
{
    if(getCookie(name))
    {
        var expdate = new Date(); 
        expdate.setTime(expdate.getTime() - 86400000); 
        setCookie(name, "", expdate);
        expdate = null;
    }
};

/***************************** Dom 操作 *****************************/
var __uniqueId = Math.randomInt(10000) + 10000;  // 计数器
/// 获得全局唯一 id
// prefix   可选，前缀
window.getUniqueId = function(/*String?*/ prefix)
{
    prefix = prefix || "";
    __uniqueId++;
    return prefix + __uniqueId;  // String
};
// 全局对象池
var __pool = {};
/// 在全局对象池中，增加一个对象
// obj     全局对象
window.addGlobal = function(/*Object*/ obj)
{
    if (!obj)
    {
        return;
    }
    if (obj.id && !__pool[obj.id])
    {
        __pool[obj.id] = obj;
    }
    else
    {
        obj.id = getUniqueId(); // 新增或覆盖 obj.id
        __pool[obj.id] = obj;
    }
};
/// 从全局对象池中，获得指定 id 的对象
// id       用 getUniqueId 方法生成的 id
window.getGlobal = function(/*String*/ id)
{
    return __pool[id] || null; // Object|null
};


/***************************** Ajax 操作 *****************************/
/****** 解析 Xml ******/
// 根据 Xml 字符串，创建 XMLDocument 对象
// xml      可选，一段 Xml（只有一个根节点）
function __createXMLDocument(/*Xml?*/ xml)
{
    if (xml && typeof DOMParser != "undefined")
    {
        var parser = new DOMParser();
        return parser.parseFromString(xml, "text/xml");	// XMLDocument
    }
    else if (typeof ActiveXObject != "undefined")
    {
        var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
        for (var i = 0, l = prefixes.length; i < l; i++)
        {
            try
            {
                var doc = new ActiveXObject(prefixes[i] + ".XMLDOM");
                if (xml)
                {
                    if (doc)
                    {
                        doc.async = false;
                        doc.loadXML(xml);
                        return doc;	// XMLDocument
                    }
                    else
                    {
                        __apiError("无法创建 XMLDocument 对象");
                        return null; // null
                    }
                }
                else
                {
                    if (doc)
                    { 
                        return doc; // XMLDocument
                    }
                }
            }
            catch (e){};
        }
    }
    else if ((document.implementation) && (document.implementation.createDocument))
    {
        if (xml)
        {
            if (document.createElement)
            {
                var tmp = document.createElement("xml");
                tmp.innerHTML = xml;
                var xmlDoc = document.implementation.createDocument("bbl", "", null);
                for (var i = 0, l = tmp.childNodes.length; i < l; i++)
                {
                    xmlDoc.importNode(tmp.childNodes.item(i), true);
                }
                return xmlDoc; // XMLDocument
            }
        }
        else
        {
            return document.implementation.createDocument("", "", null); // XMLDocument
        }
    }
    __apiError("无法创建 XMLDocument 对象");
    return null; // null
}
// 检验 XMLDocument 对象是否包含正确的数据
// xmlDoc   待检验的 XMLDocument 对象
function __isValidXMLDocument(/*XMLDocument*/ xmlDoc)
{
    return !!(xmlDoc
              && xmlDoc.documentElement
              && xmlDoc.documentElement.tagName
              && (xmlDoc.documentElement.tagName.toLowerCase() != "parsererror")
              && (xmlDoc.documentElement.getElementsByTagName("parsererror").length == 0)
              && (!xmlDoc.parseError || xmlDoc.parseError && !xmlDoc.parseError.errorcode)); // Boolean
}
// 获得 XmlNode 同名子节点的数组（不包含孙节点或曾孙节点等）
// xmlNode  Xml 节点
// 要查找的元素名
function __getXmlNodeSameNameChildren(/*XmlNode*/ xmlNode, /*String*/ name)
{
    if (!xmlNode || !xmlNode.getElementsByTagName)
    {
        return null;
    }
    var sameNameChildren = [];
    var sameNameNodes = xmlNode.getElementsByTagName(name);
    if (sameNameNodes && sameNameNodes.length)
    {
        for (var i = 0, l = sameNameNodes.length; i < l; i++)
        {
            var sameNameNode = sameNameNodes[i];
            if (sameNameNode.parentNode == xmlNode)
            {
                sameNameChildren.push(sameNameNode);
            }
        }
    }
    xmlNode = null;
    name = null;
    sameNameNodes = null;
    i = null;
    l = null;
    return sameNameChildren;
}
// 以递归方式，获得 XmlNode 所表示的值，规则如下：
// <y></y>                           --> y = ""
// <y>value</y>                      --> y = "value"
// <y><x>value</x></y>               --> y.x = "value"
// <y><x>value1</x><x>value2</x></y> --> y.xList = ["value1", "value2"]
// xmlNode  Xml 节点
// listNames    强制转换为数组的元素名列表
function __getXmlNodeValue(/*XmlNode*/ xmlNode, /*String[]*/ listNames)
{
    if (!xmlNode)
    {
        return null; // null 忽略该节点
    }
    var value = null;
    var childNodes = xmlNode.childNodes;
    var childCount = childNodes.length;
    if (!childNodes || !childCount) // 空节点
    {
        value = ""; // String
    }
    else
    {
        if (childCount == 1) // 单节点
        {
            var firstChild = childNodes[0];
            switch (firstChild.nodeType)
            {
                case 1: // 元素
                    value = value || {};
                    var name = firstChild.nodeName;
                    if (listNames.contains(name)) // 需强制转换为数组
                    {
                        var valueList = value[name + "List"] = []; // Array
                        valueList.push(arguments.callee(firstChild, listNames));
                    }
                    else
                    {
                        value[name] = arguments.callee(firstChild, listNames); // Object
                    }
                    break;
                case 3: // 文本
                    value = firstChild.data; // String
                    break;
                default: // 其它节点
                    value = null; // null 忽略该节点
                    break;
            }
        }
        else // 多节点
        {
            value = {};
            var names = []; // 已处理的元素名列表
            for (var i = 0; i < childCount; i++) // 循环每个节点
            {
                var childNode = childNodes[i];
                if (childNode.nodeType == 1) // 元素
                {
                    var name = childNode.nodeName;
                    var sameNameNodes;
                    // 在同层次中，查找同名元素
                    if (typeof xmlNode.selectNodes != "undefined")
                    {
                        sameNameNodes = xmlNode.selectNodes("./" + name); // 优先使用 XPath，提高性能
                    }
                    else
                    {
                        sameNameNodes = __getXmlNodeSameNameChildren(xmlNode, name); // 使用自定义方法
                    }
                    if (sameNameNodes && sameNameNodes.length > 1 || listNames.contains(name)) // 需转换为数组
                    {
                        if (!names.contains(name)) // 该元素名未处理
                        {
                            var valueList = value[name + "List"] = []; // Array
                            for (var j = 0, sl = sameNameNodes.length; j < sl; j++) // 循环每个同名元素
                            {
                                var sameNameNode = sameNameNodes[j];
                                valueList.push(arguments.callee(sameNameNode, listNames));
                            }
                            names.push(name); // 记入已处理的元素名列表
                        }
                        else // 该元素名已处理
                        {
                            continue; // 忽略已处理的同名元素
                        }
                    }
                    else // 在同层次中没有同名元素，并且没有指定强制转换为数组
                    {
                        value[name] = arguments.callee(childNode, listNames); // Object
                    }
                }
                else // 其它子节点
                {
                    continue; // 忽略除元素以外的其它子节点
                }
            }
        }
    }
    xmlNode = null;
    listNames = null;
    childNodes = null;
    childCount = null;
    firstChild = null;
    names = null;
    i = null;
    childNode = null;
    name = null;
    sameNameNodes = null;
    valueList = null;
    j = null;
    sl = null;
    sameNameNode = null;
    
    return value; // String|Object|Array|null
}
/// Xml 转换成 Object，转换失败时返回 null
// xml          格式良好的一段 Xml（只有一个根节点，英文元素名，并且只有元素没有属性）
// listNames    可选，强制转换为数组的元素名或其列表
window.xmlToObject = function(/*Xml*/ xml, /*String|String[]?*/ listNames)
{
    // 如果 xml 为空或 xml 不是格式良好的，则返回 null
    if (!xml || !isString(xml) || !xml.trim())
    {
        xml = null;
        return null; // null;
    }
    var xmlDoc = __createXMLDocument(xml);
    if (!__isValidXMLDocument(xmlDoc))
    {
        xml = null;
        xmlDoc = null;
        return null; // null
    }
    // 初始化强制转换为数组的元素名
    if (listNames)
    {
        if (typeof listNames == "string")
        {
            listNames = [listNames];
        }
    }
    else
    {
        listNames = [];
    }
    // 递归获得所表示的值
    var obj = __getXmlNodeValue(xmlDoc.documentElement, listNames);
    // 如果值为字符串，则转换为对象
    if (typeof obj == "string")
    {
        obj = new String(obj);
    }
    xml = null;
    listNames = null;
    xmlDoc = null;
    gc();
    return obj; // Object|null
};
/****** Http 请求 ******/
// 创建 XMLHttpRequest 对象
function __createXMLHttpRequest()
{
    var xhr = null;
    var msProgs = ["Microsoft.XMLHTTP", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"];
    for (var i = 0, l = msProgs.length; i < l; i++)
    {
        try
        {
            xhr = new ActiveXObject(msProgs[i]);
            break;
        }
        catch (e){}
    }
    if (!xhr)
    {
        try
        {
　          xhr = new XMLHttpRequest();
        }
        catch (e){}
    }
    if (!xhr)
    {
        __apiError("无法创建 XMLHttpRequest 对象");
        return null; // null
    }
    return xhr; // XMLHttpRequest
}
// 观测 InFlight 时的循环句柄
var __inFlightInterval = null;
// 当前的 InFlight 队列，数据格式见 InFlight
var __inFlights = [];
/*==数据格式定义==
XhrArgs
InFlight = {}
    // xhr:         XMLHttpRequest  该异步请求使用的 XMLHttpRequest 对象
    // xhrArgs:     XhrArgs         请求参数，数据格式见 XhrArgs
    // startTime:   int?            请求的开始时间的毫秒数
=====*/
// 观察正在进行中的异步请求
function __watchInFlight()
{
    var now = (new Date()).getTime();
    for (var i = 0, l = __inFlights.length, inFlight; (i < l) && (inFlight = __inFlights[i]); i++)
    {
        var xhr = inFlight.xhr;
        try
        {
            if (!xhr || !xhr.readyState)
            {
                __inFlights.splice(i--, 1); // 从 InFlight 队列移出
            }
            else if (xhr.readyState == 4) // 如果响应加载完成
            {
                __inFlights.splice(i--, 1); // 从 InFlight 队列移出
                var status = xhr.status || 0;
                if (status >= 200 && status < 300
                    || status == 304
                    || status == 1223
                    || !status && (window.location.protocol == "file:" || window.location.protocol == "chrome:")) // 如果 http 响应状态正常
                {
                    if (typeof inFlight.xhrArgs.load == "function")
                    {
                        inFlight.xhrArgs.load(xhr.responseText); // 执行处理方法
                    }
                }
                else
                {
                    if (typeof inFlight.xhrArgs.error == "function")
                    {
                        inFlight.xhrArgs.error("http status error", status); // http 响应状态错误
                    }
                }
            }
            else if (inFlight.startTime)
            {
                if (inFlight.startTime + (inFlight.xhrArgs.timeout || 0) < now) // 请求过期
                {
                    __inFlights.splice(i--, 1); // 从 InFlight 队列移出
                    if (typeof inFlight.xhrArgs.error == "function")
                    {
                        inFlight.xhrArgs.error("timeout"); // 请求过期
                    }
                    if (typeof xhr.abort == "function" || typeof xhr.abort == "unknown")
                    {
                        xhr.abort(); // 停止请求
                    }
                }
            }
        }
        catch (e)
        {
            if (typeof inFlight.xhrArgs.error == "function")
            {
                inFlight.xhrArgs.error("__watchInFlight error", e.description); // 观察 InFlight 出错
            }
        }
    }
    // 当没有 InFlight 时，停止定期观察
    if (!__inFlights.length)
    {
        window.clearInterval(__inFlightInterval);
        __inFlightInterval = null;
        return;
    }
}
// 增加一个正在进行中的异步请求
// inFlight     一个正在进行中的异步请求，数据格式见 InFlight
function __addInFlight(/*InFlight*/ inFlight)
{
    if (inFlight.xhrArgs.timeout) // 如果设置了过期时长
    {
        inFlight.startTime = (new Date()).getTime(); // 记录请求开始时间
    }
    __inFlights.push(inFlight); // 加入观察队列
    if (!__inFlightInterval)
    {
        __inFlightInterval = window.setInterval(__watchInFlight, 50); // 开始定期观察
    }
    __watchInFlight(); // 进行观察
}
// 检查请求的 Url 或请求参数
// xhrArgs    请求的 Url 或请求参数，数据格式见 XhrArgs
function __validateXhrArgs(/*Url|XhrArgs*/ xhrArgs)
{
    if (xhrArgs && typeof xhrArgs == "string")
    {
        xhrArgs = {
                        url:    xhrArgs,
                        method: "get",
                        sync:   true
                  };
    }
    if (!xhrArgs || !xhrArgs.url || typeof xhrArgs.url != "string")
    {
        __apiError("http请求时，未传入url");
    }
    return xhrArgs; // XhrArgs
}
/// 判断是否为一个 XhrArgs 对象
// obj      待判断的对象
window.isXhrArgs = function(/*Object*/ obj)
{
    return !!(obj && obj.url && isString(obj.url)); // Boolean
};
/*==数据格式定义==
XhrArgs = {}
    -- 必需
    // url:         String      请求的 Url，"tms" 是保留键
    -- 请求方式
    // method:      String?     可选，请求类型，"get" 或 "post"，默认为 "post"
    // sync:        Boolean?    可选，true: 同步请求  false: 异步请求，默认为 true
    // content:     Object?     可选，请求内容的键值对，get 请求时的查询字符串，post 请求时的包体，"tms" 是保留键
    // headers:     Object?     可选，http 包头的键值对
    -- 事件处理
    // load:        Function?   可选，请求成功的处理方法
    // timeout:     int?        可选，异步请求过期时长，单位为毫秒
    // error:       Function?   可选，请求出错或过期时的处理方法
=====*/
/// 发起 http get 请求，同步请求时返回响应文本
// xhrArgs    请求的 Url 或请求参数，数据格式见 XhrArgs
window.xhrGet = function(/*Url|XhrArgs*/ xhrArgs)
{
    xhrArgs = __validateXhrArgs(xhrArgs);
    xhrArgs.method = "get";
    return xhrRequest(xhrArgs); // String
};
/// 发起 http post 请求，同步请求时返回响应文本
// xhrArgs    请求的 Url 或请求参数，数据格式见 XhrArgs
window.xhrPost = function(/*Url|XhrArgs*/ xhrArgs)
{
    xhrArgs = __validateXhrArgs(xhrArgs);
    xhrArgs.method = "post";
    return xhrRequest(xhrArgs); // String
};
/// 发起 http 请求，同步请求时返回响应文本
// xhrArgs    请求的 Url 或请求参数，数据格式见 XhrArgs
window.xhrRequest = function(/*Url|XhrArgs*/ xhrArgs)
{
    // 初始化请求参数
    xhrArgs = __validateXhrArgs(xhrArgs);
    xhrArgs.method = (xhrArgs.method == "get" ? "get" : "post");
    xhrArgs.sync = xhrArgs.sync !== false;
    if (!xhrArgs.sync && xhrArgs.timeout && typeof xhrArgs.error != "function")
    {
        __apiError("http异步请求时，设置了timeout，但error方法为空");
        return null; // null
    }
    var url = xhrArgs.url;
    var content = xhrArgs.content ? objectToQuery(xhrArgs.content) : null;
    if (xhrArgs.method == "get" && content)
    {
        url += (url.indexOf("?") == -1 ? "?" : "&") + content;
    }
    url += (url.indexOf("?") == -1 ? "?" : "&") + "tms=" + (new Date()).getTime(); // 记录请求时间，清除 IE 缓存
    // 创建 XMLHttpRequest 对象
    var xhr = __createXMLHttpRequest();
    // 初始化请求
    xhr.open(xhrArgs.method, url, !xhrArgs.sync);
    // 设置 http 包头
    var contentType = "application/x-www-form-urlencoded"; // 默认的 Content-Type
    if (xhrArgs.headers)
    {
        for (var headerKey in xhrArgs.headers)
        {
            var headerValue = xhrArgs.headers[headerKey];
            if (typeof headerValue == "string" || typeof headerValue == "number")
            {
                if (headerKey.toLowerCase() === "content-type" && headerValue)
                {
                    contentType = headerValue.toString();
                }
                else
                {
                    xhr.setRequestHeader(headerKey, headerValue.toString());
                }
            } 
        }
    }
    xhr.setRequestHeader("Content-Type", contentType);
    // 发送请求
    try
    {
        xhr.send(xhrArgs.method == "get" ? null : content);
    }
    catch (e)
    {
        if (typeof xhr.abort == "function" || typeof xhr.abort == "unknown")
        {
            xhr.abort(); // 停止请求
        }
        __apiError("http请求发送时出错");
        return null; // null
    }
    
    content = null;
    contentType = null;
    headerKey = null;
    headerValue = null;
    
    if (xhrArgs.sync) // 同步请求
    {
        var response = xhr.responseText;
        xhr = null;
        xhrArgs = null;
        return response; // String
    }
    else // 异步请求
    {
        var inFlight = {xhr: xhr, xhrArgs: xhrArgs};
        __addInFlight(inFlight); // 增加一个正在进行中的异步请求
        xhr = null;
        xhrArgs = null;
        inFlight = null;
        return null; // null
    }
};

/***************************** Widget 基础方法 *****************************/
/// 获得节点在窗口中的偏移位置
// domNode  节点或它的 id
window.getDomNodeOffsetPos = function(/*String|DomNode*/ domNode)
{
    domNode = $(domNode);
    if (!domNode.parentNode || domNode.style.display == 'none')
    {
       return null; // null
    }
    var pos;
    if (domNode.getBoundingClientRect) // IE
    {
       var box = domNode.getBoundingClientRect();
       var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
       var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
       pos = [box.left + scrollLeft, box.top + scrollTop];
    }
    else
    {
        if (document.getBoxObjectFor) // gecko
        {
           var box = document.getBoxObjectFor(domNode);
           var borderLeft = toInt(domNode.style.borderLeftWidth, 0);
           var borderTop = toInt(domNode.style.borderTopWidth, 0);
           pos = [box.x - borderLeft, box.y - borderTop];
        }
        else // opera 或 safari
        {
           pos = [domNode.offsetLeft, domNode.offsetTop];
           var parent = domNode.offsetParent;
           if (parent != domNode)
           {
                while (parent)
                {
                    pos[0] += parent.offsetLeft;
                    pos[1] += parent.offsetTop;
                    parent = parent.offsetParent;
                }
           }
           if (isOpera || (isSafari && domNode.style.position == 'absolute'))
           {
                pos[0] -= document.body.offsetLeft;
                pos[1] -= document.body.offsetTop;
           }
        }
        parent = domNode.parentNode || null;
        // 叠加所有祖先节点
        while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML')
        {
           pos[0] -= parent.scrollLeft;
           pos[1] -= parent.scrollTop;
           parent = parent.parentNode || null;
        }
    }
    return pos; // Position
};
/*==数据格式定义==
Position = []
    // 0:          int   left，左偏移，单位为像素
    // 1:          int   top ，上偏移，单位为像素
=====*/
/// 获得窗口的滚动位置
// win      可选，窗口，默认为 window
window.getWindowScrollPos = function(/*Window?*/ win)
{
    win = win || window;
    var scrollLeft;
    var scrollTop; 
    if (typeof win.pageYOffset != 'undefined')
    { 
       scrollLeft = win.pageXOffset; 
       scrollTop = win.pageYOffset; 
    }
    else if (win.document.compatMode && win.document.compatMode != 'BackCompat')
    { 
       scrollLeft = win.document.documentElement.scrollLeft;
       scrollTop = win.document.documentElement.scrollTop; 
    }
    else if (win.document.body)
    { 
       scrollLeft = win.document.body.scrollLeft;
       scrollTop = win.document.body.scrollTop; 
    }
    win = null;
    return [scrollLeft, scrollTop];  // Position
};

/***************************** Widget *****************************/
/*==数据格式定义==
PagerArgs = {}
    -- 必需
    // data:                int|Object[]|Url|XhrArgs    int：服务器端分页时的总记录数，Object[]：客户端分页时的总数据，Url|XhrArgs：获得总记录数或总数据的请求地址或请求参数，数据格式见 XhrArgs
    -- 分页状态
    // pageSize:            int?                        可选，每页记录条数
    // currentPage:         int?                        可选，初始时为第几页
    // onTurnPage:          Function?                   可选，翻页的事件处理方法
    -- 数据源
    // perPageUrl:          Url|XhrArgs?                可选，服务器端分页时，每页数据的请求地址或请求参数，数据格式见 XhrArgs
    // xmlName:             String?                     可选，在 Xml 中，需要强制转换为数组的元素名
    -- 显示样式
    // domNode:             String|DomNode?             可选，分页控件的节点或它的 id
    // mode:                int?                        可选，使用第几套模板，1: 大分页栏  2: 小分页栏  3: 不带总条数的小分页栏
    // nearbyPageCount:     int?                        可选，显示相邻的多少个页号
=====*/
/// 分页栏类
// args     分页栏的参数，数据格式见 PagerArgs
window.Pager = function(/*PagerArgs*/ args)
{
    if (!args || !args.data && args.data !== 0)
    {
        __apiError("创建 Pager 对象时具有无效参数!");
        return;
    }
    if (args.perPageUrl && !args.xmlName)
    {
        __apiError("perPageUrl 和 xmlName 必须同时给出!");
        return;
    }
    this.init(args);
};
window.Pager.prototype = 
{
    id:                 null,       // 只读，该 Pager 实例的 id
    // 分页状态
    count:              null,       // 只读，记录总条数
    pageSize:           10,         // 只读，每页记录条数
    currentPage:        1,          // 只读，当前第几页（从 1 开始）
    totalPage:          null,       // 只读，总页数
    startIndex:         null,       // 只读，当前页第一条记录的位置（从零开始）
    endIndex:           null,       // 只读，当前页最后一条记录的位置（从零开始）
    // 数据源
    clientData:         null,       // 只读，可空，客户端分页时的总数据，服务器端分页时为 null
    perPageUrl:         null,       // 读写，可空，服务器端分页时，每页数据的请求地址或请求参数
    xmlName:            null,       // 读写，可空，在 Xml 中，需要强制转换为数组的元素名
    // 显示样式
    domNode:            null,       // 读写，可空，分页栏的节点
    mode:               1,          // 读写，使用第几套模板，默认为 1，1: 大分页栏  2: 小分页栏  3: 不带总条数的小分页栏
    nearbyPageCount:    5,          // 读写，显示相邻的多少个页号，默认为 5
    /// 初始化
    // args     分页栏的参数，数据格式见 PagerArgs
    init: function(/*PagerArgs*/ args)
    {
        // 获得总数据
        var argsData = args.data;
        if (argsData || argsData === 0)
        {
            var isXhrArgs = window.isXhrArgs(argsData);
            if (isString(argsData) || isXhrArgs) // 如果为 Url 或 XhrArgs
            {
                if (isXhrArgs)
                {
                    argsData.sync = true; // 强制转换为同步请求
                }
                var response = xhrRequest(argsData); // 通过 Url 或 XhrArgs，获得服务器端分页时的总记录数，或客户端分页时的总数据
                var data = xmlToObject(response, args.xmlName);
                if (data) // 获得 Object[]
                {
                    if (!args.xmlName || isArray(args.xmlName) && !args.xmlName.length)
                    {
                        __apiError("xmlName 未给出!");
                        return;
                    }
                    argsData = data[(isArray(args.xmlName) ? args.xmlName[0] : args.xmlName)  + "List"] || [];
                }
                else // 获得 int
                {
                    argsData = toInt(response, -1);
                }
            }
            if (isArray(argsData)) // 如果为 Object[]
            {
                this.clientData = argsData;
                this.count = argsData.length;
            }
            if (isNumber(argsData)) // 如果为 int
            {
                this.count = toInt(argsData, -1);
            }
        }
        if (!this.count && this.count !== 0 || this.count < 0)
        {
            __apiError("创建 Pager 对象时具有无效参数!");
            return;
        }
        if (!this.id) // 如果第一次初始化
        {
            this.id = getUniqueId("Pager");
            __addPager(this); // 存入全局对象池
            this._triggerOnTurnPage = this._triggerOnTurnPage.hitch(this);
        }
        // 赋值
        if (args.pageSize)
        {
            this.pageSize = args.pageSize;
        }
        if (args.currentPage)
        {
            this.currentPage = args.currentPage;
        }
        if (args.onTurnPage)
        {
            this.onTurnPage = args.onTurnPage;
        }
        if (args.perPageUrl)
        {
            this.perPageUrl = args.perPageUrl;
        }
        if (args.xmlName)
        {
            this.xmlName = args.xmlName;
        }
        if ($(args.domNode))
        {
            this.domNode = $(args.domNode);
        }
        if (args.mode)
        {
            this.mode = args.mode;
        }
        if (args.nearbyPageCount)
        {
            this.nearbyPageCount = args.nearbyPageCount;
        }
        // 调整分页状态
        this._regulate();
        // 绘制分页栏
        if (this.domNode)
        {
            this.domNode.innerHTML = this.getHtml();
        }
        // 触发 onTurnPage 事件
        this._triggerOnTurnPage();
        
        argsData = null;
        isXhrArgs = null;
        response = null;
        data = null;
    },
    // 调整分页状态
    _regulate: function()
    {
        if (this.count === 0) // 如果没有记录
        {
            this.currentPage = 1;
            this.totalPage = 1;
            this.startIndex = 0;
            this.endIndex = 0;
        }
        else // 如果有记录
        {
            this.totalPage = Math.floor(((this.count - 1) / this.pageSize) + 1);
            // 调整 this.currentPage
            if (this.currentPage < 1)
            {
                this.currentPage = 1;
            }
            if (this.currentPage > this.totalPage)
            {
                this.currentPage = this.totalPage;
            }
            // 调整 this.startIndex
            this.startIndex = (this.currentPage - 1) * this.pageSize;
            // 调整 this.endIndex
            this.endIndex = this.startIndex + this.pageSize - 1;
            if (this.endIndex > this.count - 1)
            {
                this.endIndex = this.count - 1;
            }
        }
    },
    // 获得与当前页相邻的页号
    // nearbyPageCount   获得相邻的多少个页号
    _getNearbyPages: function(/*int*/ nearbyPageCount)
    {
        var startPage = this.currentPage - Math.floor(nearbyPageCount / 2);
        var endPage = this.currentPage + Math.round((nearbyPageCount - 1.5) / 2);
        var totalPage = this.totalPage;
        if (endPage < startPage)
        {
            endPage = startPage;
        }
        while (startPage < 1)
        {
            startPage++;
            if (endPage < totalPage)
            {
                endPage++;
            }
        }
        while (endPage > totalPage)
        {
            endPage--;
            if (startPage > 1)
            {
                startPage--;
            }
        }
        var result = [];
        for (var i = startPage; i <= endPage; i++)
        {
            result.push(i);
        }
        startPage = null;
        endPage = null;
        totalPage = null;
        i = null;
        return result;  // int[]
    },
    // 触发 onTurnPage 事件
    // response     可空，异步请求后返回的 Xml
    _triggerOnTurnPage: function(/*Xml?*/ response)
    {
        var currPage = this.currentPage;
        var pageSize = this.pageSize;
        var id = this.id;
        if (!isUndefined(response)) // 异步请求后触发 onTurnPage 事件
        {
            var data = xmlToObject(response, this.xmlName);
            if (data)
            {
                this.onTurnPage(currPage, data[(isArray(this.xmlName) ? this.xmlName[0] : this.xmlName) + "List"] || [], id);
            }
            else
            {
                this.onTurnPage(currPage, null, id);
            }
        }
        else
        {
            if (this.clientData) // 客户端分页时
            {
                this.onTurnPage(currPage, this.getPagedData(), id);
            }
            else // 服务器端分页时
            {
                var perPageUrl = this.perPageUrl;
                var isXhrArgs = window.isXhrArgs(perPageUrl);
                if (this.xmlName
                    && perPageUrl
                    && (isString(perPageUrl) || isXhrArgs))  // 如果指定每页数据的请求地址
                {
                    if (isString(perPageUrl))
                    {
                        // 形成异步请求
                        perPageUrl = {
                                        url:        perPageUrl,
                                        method:     "get",
                                        sync:       false
                                     };
                    }
                    // 覆盖分页状态参数
                    var indexOfquestionMark = perPageUrl.url.indexOf("?");
                    if (indexOfquestionMark != -1)
                    {
                        var url = perPageUrl.url.substring(0, indexOfquestionMark);
                        var queryString = perPageUrl.url.substring(indexOfquestionMark + 1);
                        if (queryString)
                        {
                            var urlObject = queryToObject(queryString);
                            urlObject.index = currPage;
                            urlObject.size = pageSize;
                            perPageUrl.url = url + "?" + objectToQuery(urlObject);
                        }
                    }
                    // 强制转换为异步请求
                    perPageUrl.sync = false;
                    // 指定并覆盖 load 事件处理方法
                    perPageUrl.load = this._triggerOnTurnPage;
                    // 发送每页的异步请求
                    xhrRequest(perPageUrl);
                }
                else // 如果没有指定每页数据的请求地址
                {
                    this.onTurnPage(currPage, null, id);
                }
            }
        }
        currPage = null;
        pageSize = null;
        data = null;
        perPageUrl = null;
        isXhrArgs = null;
        indexOfquestionMark = null;
        url = null;
        queryString = null;
        urlObject = null;
    },
    /// 翻页
    // targetPage   翻到第几页
    turnPage: function(/*int*/ targetPage)
    {
        // 调整分页状态
        targetPage = toInt(targetPage, 1);
        if (targetPage < 1)
        {
            targetPage = 1;
        }
        if (targetPage > this.totalPage)
        {
            targetPage = this.totalPage;
        }
        if (this.currentPage != targetPage)
        {
            this.currentPage = targetPage;
            this._regulate();
        }
        // 重绘分页栏
        if (this.domNode)
        {
            this.domNode.innerHTML = this.getHtml();
        }
        // 无论页号是否发生变化，都会触发 onTurnPage 事件
        this._triggerOnTurnPage();
    },
    /// 翻到下一页
    nextPage: function()
    {
        this.turnPage(this.currentPage + 1);
    },
    /// 翻到上一页
    prevPage: function()
    {
        this.turnPage(this.currentPage - 1);
    },
    /// 翻到首页
    firstPage: function()
    {
        this.turnPage(1);
    },
    /// 翻到末页
    lastPage: function()
    {
        this.turnPage(this.totalPage);
    },
    /// 客户端分页时，获得当前页的数据
    getPagedData: function()
    {
        var result = [];
        var clientData = this.clientData;
        if (isArray(clientData))
        {
            if (clientData.length > 0)
            {
                var endIndex = this.endIndex;
                for (var i = this.startIndex; i <= endIndex; i++)
                {
                    result.push(clientData[i]);
                }
                endIndex = null;
                i = null;
            }
        }
        else
        {
            __apiError("没有客户端总数据!");
        }
        clientData = null;
        return result;  // Array
    },
    /// 获得分页栏的 Html
    // mode                 可选，使用第几套模板，1: 大分页栏  2: 小分页栏  3: 不带总条数的小分页栏  4: 不带总条数的大分页栏，默认为 this.mode
    // nearbyPageCount      可选，显示相邻的多少个页号，默认为 this.nearbyPageCount
    getHtml: function(/*int?*/ mode, /*int?*/ nearbyPageCount)
    {
        if (!mode && mode !== 0)
        {
            mode = this.mode;
        }
        if (!nearbyPageCount && nearbyPageCount !== 0)
        {
            nearbyPageCount = this.nearbyPageCount;
        }
        var id = this.id;
        var currentPage = this.currentPage;
        var totalPage = this.totalPage;
        var html = "";
        switch (mode)
        {
            case 1:
            case 4:
                html += "<div class='pages'>";
                if (mode == 1)
                {
                    html += "<span class='stastic'>共有<em>" + this.count + "</em>条记录</span>";
                }
                html += "<a class='nextprev' ";
                html += ((currentPage == 1) ? "" : ("href='#' onclick='$Pager(\"" + id + "\").firstPage(); return false;'")) + ">第一页</a>";
                var pages = this._getNearbyPages(nearbyPageCount);
                for (var i = 0, l = pages.length; i < l; i++)
                {
                    var page = pages[i];
                    if (currentPage == page)
                    {
                        html += "<span class='Nolink current'>" + page + "</span>";
                    }
                    else
                    {
                        html += "<a href='#' onclick='$Pager(\"" + id + "\").turnPage(" + page + "); return false;'>" + page + "</a>";
                    }
                }
                html += "<a class='nextprev' ";
                html += ((currentPage == totalPage) ? "" : ("href='#' onclick='$Pager(\"" + id + "\").lastPage(); return false;'")) + ">最后一页</a>";
                html += "<span class='skip'>跳转到&nbsp;<select onchange='$Pager(\"" + id + "\").turnPage(this.value)'>";
                for (var j = 1; j <= totalPage; j++)
                {
                    html += "<option value='" + j + "'";
                    if (j == currentPage)
                    {
                        html += " selected='selected'";
                    }
                    html += ">" + j + "</option>";
                }
                html += "</select>&nbsp;页</span></div>";
                break;
            case 2:
            case 3:
                html += "<div class='pages'>";
                if (mode == 2)
                {
                    html += "<span class='stastic'>共<em>" + this.count + "</em>条</span>";
                }
                html += "<a class='nextprev' ";
                html += ((currentPage == 1) ? "" : ("href='#' onclick='$Pager(\"" + id + "\").firstPage(); return false;'")) + ">首页</a>";
                var pages = this._getNearbyPages(nearbyPageCount);
                for (var i = 0, l = pages.length; i < l; i++)
                {
                    var page = pages[i];
                    if (currentPage == page)
                    {
                        html += "<span class='Nolink current'>" + page + "</span>";
                    }
                    else
                    {
                        html += "<a href='#' onclick='$Pager(\"" + id + "\").turnPage(" + page + "); return false;'";
                        html += ">" + page + "</a>";
                    }
                }
                html += "<a class='nextprev' ";
                html += ((currentPage == totalPage) ? "" : ("href='#' onclick='$Pager(\"" + id + "\").lastPage(); return false;'")) + ">末页</a>";
                html += "</div>";
                break;
        }
        id = null;
        currentPage = null;
        totalPage = null;
        pages = null;
        i = null;
        l = null;
        j = null;
        return html;
    },
    /// 事件，翻页后触发
    // currPage     当前第几页
    // data         可空，当前页的数据，客户端分页或给出了 args.perPageUrl 时该参数有值
    // pagerId      当前分页栏的 id，可以通过 $Pager(pagerId) 获得该分页栏的引用
    onTurnPage: function(/*int*/ currPage, /*Object[]?*/ data, /*String*/ pagerId) {}
};
// 在全局对象池中存入 Pager 对象
function __addPager(/*Pager*/ pager)
{
    if (pager && pager instanceof Pager)
    {
        addGlobal(pager);
    }
}
/// 在全局对象池中获得指定 id 的 Pager 对象
// 用 getUniqueId 方法生成的 Pager 对象的 id
window.$Pager = function(/*String*/ id)
{
    var pager = getGlobal(id);
    if (!pager || !pager instanceof Pager)
    {
        __apiError("没有指定的Pager对象");
        return null; // null
    }
    return pager; // Pager
};

/// 提示框类
window.Tooltip = function() {};
window.Tooltip.prototype = 
{
    id:             null,   // 只读，该 Tooltip 实例的id
    /// 弹出提示框
    // aroundNode   节点或它的 id，在该节点上弹出提示框
    // content      提示框中的 Html
    // width        可选，提示框宽度，单位为像素，如：100，默认为自动调整宽度
    // hasTitleBar  可选，是否有标题栏，默认为 false
    // title        可选，标题栏上的标题，一段 Html，默认为空
    show:           function(/*String|DomNode*/ aroundNode, /*Html*/ content, /*int?*/ width, /*Boolean?*/ hasTitleBar, /*Html?*/ title)
                    {
                        if (this.id)
                        {
                            this.close();
                        }
                        aroundNode = $(aroundNode);
                        if (!aroundNode || !content)
                        {
                            __apiError("创建 Tooltip 对象时具有无效参数!");
                            return;
                        }
                        // 设置默认值
                        width = parseInt(width);
                        width = isNaN(width) ? null : width;
                        hasTitleBar = !!hasTitleBar;
                        title = title || "";
                        // 获得id
                        this.id = getUniqueId("Tooltip");
                        // divContainer
                        var divContainer = document.createElement("div");
                        divContainer.className = "tooltip";
                        divContainer.id = this.id;
                        // divContent
                        var divContent = document.createElement("div");
                        divContent.className = "tooltipContent";
                        // divMask
                        var divMask = document.createElement("div");
                        divMask.innerHTML = "<iframe width='100%' height='100%' frameborder='0'></iframe>";
                        divMask.style.position = "absolute";
                        divMask.id = this.id + "_mask";
                        // divHtml
                        var divHtml = document.createElement("div");
                        divHtml.innerHTML = content;
                        // imgArrow 提示框的箭头
                        var imgArrow = document.createElement("img");
                        imgArrow.style.position = "relative";
                        // 调整容器宽度
                        if (width)
                        {
                            divContainer.style.width = width + 'px';
                            divContent.style.width = width + 'px';
                        }
                        else
                        {
                            if (isIE && divHtml.firstChild && divHtml.firstChild.style.pixelWidth)
                            {
                                divContainer.style.pixelWidth = divContent.style.pixelWidth + divContent.style.pixelLeft + 12;
                                divContent.style.pixelWidth = divHtml.firstChild.style.pixelWidth + 10;
                            }
                            else
                            {
                                divContainer.style.width = 'auto';
                                divContent.style.width = 'auto';
                            }
                        }
                        
                        // 标题栏
                        if (hasTitleBar)
                        {
                            // divTitle
                            var divTitle = document.createElement("div");
                            divTitle.className = "tooltipTitle";
                            var html = "";
                            html += "<table width='100%' height='100%' cellpdding='0' cellspacing='0'><tr>";
                            html += "<td align='left' valign='middle'>" + title + "</td>";
                            html += "<td align='right' valign='middle'><img src='/JsLib/20090331/Images/tooltipclose.gif' style='cursor:pointer'></td>";
                            html += "</tr></table>";
                            divTitle.innerHTML = html;
                            divTitle.firstChild.rows[0].cells[1].onclick = this.close.hitch(this);
                            divContent.appendChild(divTitle);
                        }
                        // 组装 DOM
                        divContent.appendChild(divHtml);
                        divContainer.appendChild(divContent);
                        divContainer.appendChild(imgArrow);
                        document.body.appendChild(divMask);
                        document.body.appendChild(divContainer);
                        // 调整divMask高宽
                        divMask.style.width = divContent.style.width;
                        divMask.style.height = divContent.clientHeight;
                        divMask.firstChild.style.height = divContent.clientHeight;
                        // 判断提示框在窗口中的位置
                        var offsetPosition = getDomNodeOffsetPos(aroundNode);
                        var offsetLeft = offsetPosition[0];
                        var offsetTop = offsetPosition[1];
                        var windowScrollTop = getWindowScrollPos()[1];
                        var p1, p2;
                        if (offsetLeft + aroundNode.clientWidth + divContainer.clientWidth > document.body.clientWidth)
                        {
                            divContainer.style.left = (offsetLeft - divContainer.clientWidth) + 'px';
                            p1 = "L";   // 提示框偏左
                        }
                        else
                        {
                            divContainer.style.left = (offsetLeft + aroundNode.offsetWidth) + 'px';
                            p1 = "R";   // 提示框偏右
                        }
                        if (offsetTop - divContent.clientHeight + 20 < windowScrollTop)
                        {
                            divContainer.style.top = (offsetTop - 12) + 'px';
                            p2 = "B";   // 提示框偏下
                        }
                        else
                        {
                            divContainer.style.top = (offsetTop - divContent.clientHeight + 12) + 'px';
                            p2 = "T";   // 提示框偏上
                        }
                        // 调整箭头位置
                        if (p1 == "L")
                        {
                            if (p2 == "T")
                            {
                                divContent.style.left = '0px';
                                divContent.style.top = '0px';
                                imgArrow.style.left = (divContent.clientWidth + 1) + 'px';
                                imgArrow.style.top = '-19px';
                            }
                            else
                            {
                                divContent.style.left = '0px';
                                divContent.style.top = '0px';
                                imgArrow.style.left = (divContent.clientWidth + 1) + 'px';
                                imgArrow.style.top = (5 - divContent.clientHeight) + 'px';
                            }
                            imgArrow.src = "/JsLib/20090331/Images/tooltipConnectorRight.gif";
                        }
                        else
                        {
                            if (p2 == "T")
                            {
                                divContent.style.left = '13px';
                                divContent.style.top = '0px';
                                imgArrow.style.left = '0px';
                                imgArrow.style.top =  '-19px';
                            }
                            else
                            {
                                divContent.style.left = '13px';
                                divContent.style.top = '0px';
                                imgArrow.style.left = '0px';
                                imgArrow.style.top = (5 - divContent.clientHeight) + 'px';
                            }
                            imgArrow.src = "/JsLib/20090331/Images/tooltipConnectorLeft.gif";
                        }
                        // 调整divMask位置
                        divMask.style.left = (parseInt(divContainer.style.left) + parseInt(divContent.style.left)) + 'px';
                        divMask.style.top = (parseInt(divContainer.style.top) + parseInt(divContent.style.top)) + 'px';
                        // 回收内存
                        divContainer = null;
                        divContent = null;
                        divMask = null;
                        divHtml = null;
                        imgArrow = null;
                        divTitle = null;
                        html = null;
                        offsetPosition = null;
                        offsetLeft = null;
                        offsetTop = null;
                        windowScrollTop = null;
                        p1 = null;
                        p2 = null;
                        gc();
                    },
    /// 关闭提示框
    close:          function()
                    {
                        if (this.id)
                        {
                            document.body.removeChild($(this.id));
                            document.body.removeChild($(this.id + "_mask"));
                            this.id = null;
                            gc();
                        }
                    }
};
var __commonTooltip = new Tooltip();
/// 弹出公用提示框
// aroundNode   节点或它的 id，在该节点上弹出提示框
// content      提示框中的Html
// width        可选，提示框宽度，单位为像素，如：100，默认为自动调整宽度
// hasTitleBar  可选，是否有标题栏，默认为 false
// title        可选，标题栏上的标题，一段 Html，默认为空
window.showTooltip = function(/*String|DomNode*/ aroundNode, /*Html*/ content, /*int?*/ width, /*Boolean?*/ hasTitleBar, /*Html?*/ title)
{
    __commonTooltip.show(aroundNode, content, width, hasTitleBar, title);
};
/// 关闭公用提示框
window.closeTooltip = function()
{
    __commonTooltip.close();
};

/// 对话框类
window.Dialog = function() {this.open = this.open.hitch(this);};
window.Dialog.prototype = 
{
    isOpen:         false,  // 只读，对话框是否已打开
    isMoving:       false,  // 只读，对话框是否正在被拖拽
    hasMask:        false,  // 只读，对话框打开后，页面的其他位置是否不可点击
    
    _divMask:       null,   // 用于遮挡页面等的 iframe
    _divContainer:  null,   // 对话框的主容器
    _contentNode:   null,   // 对话框内容的节点(div)
    _mousePosX:     0,      // 鼠标位置 x
    _mousePosY:     0,      // 鼠标位置 y
    _openCount:     0,      // 尝试打开的次数
    // 鼠标停止拖拽的事件处理，上下文为标题栏 div
    _mouseDown: function(evt)
    {
        evt = evt || window.event;
        var srcElement = evt.target || evt.srcElement;
        if (srcElement.tagName.toLowerCase() != 'div')
        {
            if (this._divContainer.firstChild.setCapture)
            {
                this._divContainer.firstChild.setCapture();
            }
//            else if (window.captureEvents)
//            {
//                window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
//            }
            this.isMoving = true;
            this._mousePosX = evt.clientX || 0;
            this._mousePosY = evt.clientY || 0;
        }
    },
    // 鼠标停止拖拽的事件处理，上下文为标题栏 div
    _mouseUp: function(evt)
    {
        evt = evt || window.event;
        if (this.isMoving)
        {
            this.isMoving = false;
            if(this._divContainer.firstChild.releaseCapture)
            {
                this._divContainer.firstChild.releaseCapture();
            }
//            else if (window.releaseEvents)
//            {
//                window.releaseEvents(Event.MOUSEMOVE|Event.MOUSEUP);
//            }
            stopEvent(evt);
        }
    },
    // 鼠标拖拽时的事件处理，上下文为标题栏 div
    _mouseMove: function(evt)
    {
        if (this.isMoving)
        {
            evt = evt || window.event;
            var mousePosX = evt.clientX;
            var mousePosY = evt.clientY;
            var mPixelLeft = parseInt(this._divContainer.style.left) + mousePosX - this._mousePosX;
            var mPixelTop  = parseInt(this._divContainer.style.top) + mousePosY - this._mousePosY;
            if (mPixelLeft <= 0)
            {
                mPixelLeft = 0;
            }
            if (mPixelLeft> document.body.clientWidth - this._divContainer.clientWidth)
            {
                mPixelLeft = document.body.clientWidth - this._divContainer.clientWidth;
            }
            if (mPixelTop <= 0)
            {
                mPixelTop = 0;
            }
            this._divContainer.style.left = mPixelLeft + 'px';
            this._divContainer.style.top = mPixelTop + 'px';
            if (!this.hasMask)
            {
                var mPixelLeft = parseInt(this._divMask.style.left) + mousePosX - this._mousePosX;
                var mPixelTop  = parseInt(this._divMask.style.top) + mousePosY - this._mousePosY;
                if (mPixelLeft <= 0)
                {
                    mPixelLeft = 0;
                }
                if (mPixelLeft> document.body.clientWidth - this._divMask.clientWidth)
                {
                    mPixelLeft = document.body.clientWidth - this._divMask.clientWidth;
                }
                if (mPixelTop <= 0)
                {
                    mPixelTop = 0;
                }
                this._divMask.style.left = mPixelLeft + 'px';
                this._divMask.style.top = mPixelTop + 'px';
            }
            this._mousePosX = mousePosX;
            this._mousePosY = mousePosY;
            stopEvent(evt);
        }
    },
    /// 打开对话框
    // title    对话框的标题，一段 Html
    // content  对话框的内容，一段 Html 或页面中的一个节点(div)
    // width    可选，对话框宽度，单位为像素，如：100，默认为自动调整宽度
    // height   可选，对话框高度，单位为像素，如：100，默认为自动调整高度
    // hasMask  可选，对话框打开后，页面的其他位置是否不可点击，默认为 true
    open: function(/*Html*/ title, /*Html|DomNode*/ content, /*int?*/ width, /*int?*/ height, /*Boolean?*/ hasMask)
    {
        if (isLoaded || this._openCount >= 10)
        {
            this._openCount = 0;
            if (this.isOpen) // 对话框已打开
            {
                return;
            }
            this.isOpen = true;
            this.hasMask = hasMask !== false;
            // divContainer
            this._divContainer = document.createElement("div");
            this._divContainer.className = "dialog";
            // divMask
            this._divMask = document.createElement("div");
            this._divMask.style.position = "absolute";
            this._divMask.innerHTML = "<iframe width='100%' height='100%'" + (this.hasMask ? " style='FILTER:Alpha(opacity=20);'" : "") + " frameborder='0'></iframe>";
            // divTitle
            var divTitle = document.createElement("div");
            if (isIE)
            {
                divTitle.style.cursor = 'move';
                divTitle.onmousedown = this._mouseDown.hitch(this);
                divTitle.onmouseup = this._mouseUp.hitch(this);
                divTitle.onmousemove = this._mouseMove.hitch(this);
            }
            divTitle.className = "dialogTitle";
            var html = "";
            html += "<table width='100%' height='100%' cellpadding='0' cellspacing='0'><tr>";
            html += "<td>" + title + "</td>";
            html += "<td width='20px' valign='middle'><div class='closeButton' style='cursor:pointer'>&nbsp;</div></td>";
            html += "</tr></table>";
            divTitle.innerHTML = html;
            divTitle.firstChild.rows[0].cells[1].firstChild.onclick = this.onCloseBtnClicked.hitch(this);
            // divContent
            var divContent = document.createElement("div");
            divContent.className = "dialogContent";
            // 组装 DOM
            if (typeof content == "object") // 内容为节点
            {
                this._contentNode = content;
                divContent.appendChild(content);
                content.style.display = "";
            }
            else // 内容为 Html
            {
                divContent.innerHTML = content;
            }
            this._divContainer.appendChild(divTitle);
            this._divContainer.appendChild(divContent);
            document.body.appendChild(this._divMask); 
            document.body.appendChild(this._divContainer);
            // 调整 divContainer 的大小和位置
            if (width)
            {
                this._divContainer.style.width = width + 'px';
            }
            else
            {
                if (this._contentNode) // 内容为节点
                {
                    if (this._contentNode.clientWidth)
                    {
                        this._divContainer.style.width = this._contentNode.clientWidth + 'px';
                    }
                }
                else // 内容为 Html
                {
                    if (divContent.firstChild && divContent.firstChild.style.width)
                    {
                        this._divContainer.style.width = divContent.firstChild.style.width;
                    }
                }
            }
            if (!this._divContainer.style.width) // 默认为页面宽度的一半
            {
                 this._divContainer.style.width = (document.body.clientWidth / 2) + 'px';
            }
            
            if (height)
            {
                this._divContainer.style.height = height + 'px';
                divContent.style.height = (height - 35) + 'px';
            }
            var windowScrollPos = getWindowScrollPos();
            var windowScrollLeft = windowScrollPos[0];
            var windowScrollTop = windowScrollPos[1];
            this._divContainer.style.left = (document.documentElement.clientWidth / 2 - this._divContainer.clientWidth / 2 + windowScrollLeft) + 'px';
            this._divContainer.style.top = (200 + windowScrollTop) + 'px';
            
            // 调整 divTitle 和 divContent 的宽度
            divTitle.style.width = (parseInt(this._divContainer.style.width) - 20) + 'px'; // 减去 divTitle 的 padding
            divContent.style.width = this._divContainer.style.width;
            
            // 调整 divMask 的大小和位置
            if (this.hasMask)
            {
                // 与窗口对齐
                this._divMask.style.left = '0px';
                this._divMask.style.top  = '0px';
                this._divMask.style.width  = document.body.clientWidth + 'px';
                this._divMask.style.height = document.body.scrollHeight + 'px';
            }
            else
            {
                // 与对话框对齐
                this._divMask.style.left   = this._divContainer.style.left;
                this._divMask.style.top    = this._divContainer.style.top;
                this._divMask.style.width  = this._divContainer.style.width;
                this._divMask.style.height = this._divContainer.style.height;
            }
            // 回收内存
            divTitle = null;
            html = null;
            divContent = null;
            windowScrollPos = null;
            windowScrollLeft = null;
            windowScrollTop = null;
            gc();
        }
        else
        {
            this._openCount++;
            window.setTimeout(this.open.hitch(this, title, content, width, height, hasMask), 1000);
        }
    },
    /// 关闭对话框
    close: function()
    {
        if (this.isOpen)
        {
            this.isOpen = false;
            document.body.removeChild(this._divContainer);
            document.body.removeChild(this._divMask);
            if (this._contentNode != null) // 内容是节点
            {
                this._contentNode.parentNode.removeChild(this._contentNode);
                this._contentNode.style.display = "none";
                document.body.appendChild(this._contentNode);
                this._contentNode = null;
            }
            this._divContainer.firstChild.onmousedown = null;
            this._divContainer.firstChild.onmouseup = null;
            this._divContainer.firstChild.onmousemove = null;
            this._divContainer = null;
            this._divMask = null;
            gc();
        }
    },
    /// 事件，对话框关闭按钮点击后触发
    onCloseBtnClicked: function() {this.close();}
};
var __commonDialog = new Dialog();
/// 打开公用对话框
// title    对话框的标题，一段 Html
// content  对话框的内容，一段 Html 或页面中的一个节点(div)
// width    可选，对话框宽度，单位为像素，如：100，默认为自动调整宽度
// height   可选，对话框高度，单位为像素，如：100，默认为自动调整高度
// hasMask  可选，对话框打开后，页面的其他位置是否不可点击，默认为 true
window.openDialog = function(/*Html*/ title, /*Html|DomNode*/ content, /*int?*/ width, /*int?*/ height, /*Boolean?*/ hasMask)
{
    if (__commonDialog.isOpen)
    {
        __commonDialog.close();
    }
    __commonDialog.open(title, content, width, height, hasMask);
};
/// 关闭公用对话框
window.closeDialog = function()
{
    __commonDialog.close();
};

/*==数据格式定义==
ImageInfo = {}
    // src:         Url      图片地址
    // href:        Url      可空，链接地址
    // title:       String   可空，标题
    // summary:     Html     可空，摘要
=====*/
/// 图片框
// imgNode          img 节点或它的 id
// imageInfoList    包含图片信息的数组，每项的数据格式见 ImageInfo
// period           可选，图片自动切换的周期，单位为毫秒，默认为 0，即不自动切换
// transition       可选，图片切换效果，-1: 淡入淡出，12: 雪花，23：随机，默认为 -1
// onChange         可选，切换图片后的事件处理方法
// coerceAutoChange 可选，鼠标悬停时是否继续自动切换，默认为 false
window.ImageFrame = function(/*String|DomNode*/ imgNode, /*ImageInfo[]*/ imageInfoList, /*int?*/ period, /*int?*/ transition, /*Function?*/ onChange, /*Boolean?*/ coerceAutoChange)
{
    if (!$(imgNode) || !imageInfoList || !imageInfoList.length)
    {
        __apiError("创建 ImageFrame 对象时具有无效参数!");
        return;
    }
    this._init(imgNode, imageInfoList, period, transition, onChange, coerceAutoChange);
};
window.ImageFrame.prototype = 
{
    imgNode:            null,       // 只读，图片框节点
    imageInfoList:      null,       // 只读，包含图片信息的数组，每项的数据格式见 ImageInfo
    index:              0,          // 只读，当前显示的图片在 this.imageInfoList 的位置
    period:             0,          // 只读，图片自动切换的周期，单位为毫秒，不自动切换时为 0
    coerceAutoChange:   false,      // 只读，鼠标悬停时是否继续自动切换，默认为 false
    transition:         -1,         // 只读，图片切换效果，-1: 淡入淡出，12: 雪花，23：随机，默认为 -1
    
    _autoChangeHandler: null,       // 自动切换的 handler
    /*==数据格式定义==
    ImageInfo = {}
        // src:         Url      图片地址
        // href:        Url      可空，链接地址
        // title:       String   可空，标题
        // summary:     Html     可空，摘要
    =====*/
    // 初始化
    // imgNode          img 节点或它的 id
    // imageInfoList    包含图片信息的数组，每项的数据格式见 ImageInfo
    // period           可选，图片自动切换的周期，单位为毫秒，默认为 0，即不自动切换
    // transition       可选，图片切换效果，-1: 淡入淡出，12: 雪花，23：随机，默认为 -1
    // onChange         可选，切换图片后的事件处理方法
    // coerceAutoChange 可选，鼠标悬停时是否继续自动切换，默认为 false
    _init: function(/*String|DomNode*/ imgNode, /*ImageInfo[]*/ imageInfoList, /*int?*/ period, /*int?*/ transition, /*Function?*/ onChange, /*Boolean?*/ coerceAutoChange)
    {
        this.imgNode        = $(imgNode);
        this.imageInfoList  = imageInfoList;
        this.transition     = transition || -1;
        this.imgNode.style.filter = this.transition == -1 ? 
                                        "progid:DXImageTransform.Microsoft.Fade(Overlap=1.00);"
                                            : ("RevealTrans(duration=1,transition=" + this.transition + ")");
        if (onChange)
        {
            this.onChange = onChange;
        }
        // 初始化时将 this.index 置空
        this.index = null;
        if (!this.imgNode.src) // 如果 img 节点没有初始化
        {
            this.change(0); // 显示第一张图片
        }
        // 开始自动切换
        this.changeToNext = this.changeToNext.hitch(this);
        this.continueAutoChange = this.continueAutoChange.hitch(this);
        this.pauseAutoChange = this.pauseAutoChange.hitch(this);
        if (period && period > 0)
        {
            this.startAutoChange(period, coerceAutoChange);
        }
    },
    /// 显示指定位置的图片
    // index    图片在 this.imageInfoList 的位置
    change: function(/*int*/ index)
    {
        if (index == this.index
            || index === undefined
            || index < 0
            || index > this.imageInfoList.length - 1)
        {
            return;
        }
        this.index = index;
        var imageInfo = this.getImageInfo();
        if(imageInfo == null )
        {
            return ;
        }
        this.imgNode.src = imageInfo.src;
        this.imgNode.alt = imageInfo.title;
        var parentNode = this.imgNode.parentNode;
        if (parentNode
            && parentNode.tagName
            && parentNode.tagName.toLowerCase() == "a") // 如果父节点是 A 标签
        {
            parentNode.href = imageInfo.href;
            parentNode.title = imageInfo.title;
        }
        if (document.all) // 如果浏览器是 IE
        {
            // 呈现切换效果
            try
            {
                this.imgNode.style.visibility = "hidden";
                this.imgNode.filters[0].Apply();
                this.imgNode.style.visibility = this.imgNode.style.visibility == "visible" ? "hidden" : "visible";
                if (this.transition > 0)
                {
                    this.imgNode.filters.revealTrans.transition = this.transition;
                }
                this.imgNode.filters[0].Play();
            }
            catch (e)
            {
                this.imgNode.filters[0].Stop();
                this.imgNode.style.visibility = "visible";
            }
        }
        // 触发 onChange 事件
        this.onChange(imageInfo);
    },
    /*==数据格式定义==
    ImageInfo = {}
        // src:         Url      图片地址
        // href:        Url      可空，链接地址
        // title:       String   可空，标题
        // summary:     Html     可空，摘要
    =====*/
    /// 获得当前显示的图片信息
    getImageInfo: function()
    {
        return this.imageInfoList[this.index];
    },
    /// 切换到下一张图片
    changeToNext: function()
    {
        var index = this.index + 1;
        this.change(index > (this.imageInfoList.length - 1) ? 0 : index);
    },
    /// 开始自动切换图片
    // period               图片自动切换的周期，单位为毫秒
    // coerceAutoChange     可选，鼠标悬停时是否继续自动切换，默认为 false
    startAutoChange: function(/*int*/ period, /*Boolean?*/ coerceAutoChange)
    {
        this.period = period;
        this.coerceAutoChange = coerceAutoChange || false;
        this.continueAutoChange();
        if (!this.coerceAutoChange)
        {
            this.imgNode.onmouseover = this.pauseAutoChange;
            this.imgNode.onmouseout = this.continueAutoChange;
        }
        else
        {
            this.imgNode.onmouseover = null;
            this.imgNode.onmouseout = null;
        }
    },
    /// 继续自动切换图片
    continueAutoChange: function()
    {
        var period = this.period;
        if (period && period > 0 && !this._autoChangeHandler)
        {
            this._autoChangeHandler = window.setInterval(this.changeToNext, period);
        }
        period = null;
    },
    /// 暂停自动切换图片
    pauseAutoChange: function()
    {
        window.clearInterval(this._autoChangeHandler);
        this._autoChangeHandler = null;
    },
    /// 停止自动切换图片
    stopAutoChange: function()
    {
        this.pauseAutoChange();
        this.imgNode.onmouseover = null;
        this.imgNode.onmouseout = null;
    },
    /*==数据格式定义==
    ImageInfo = {}
        // src:         Url      图片地址
        // href:        Url      可空，链接地址
        // title:       String   可空，标题
        // summary:     Html     可空，摘要
    =====*/
    /// 事件，切换图片后触发
    // imageInfo    当前显示的图片信息，数据格式见 ImageInfo
    onChange: function(/*ImageInfo*/ imageInfo) {}
};

/// 持续滚动的节点类
// domNode       用于滚动的节点或它的 id
// width         可选，节点宽度，如：100，默认为节点当前的宽度
// height        可选，节点高度，如：100，默认为节点当前的高度
window.ScrollNode = function(/*String|DomNode*/ domNode, /*int?*/ width, /*int?*/ height)
{
    domNode = $(domNode);
    if (!domNode
        || !width && !domNode.clientWidth
        || !height && !domNode.clientHeight)
    {
        __apiError("创建 ScrollNode 对象时具有无效参数!");
    }
    this._init(domNode, width, height);
};
window.ScrollNode.prototype = 
{
    orientation:        1,          // 只读，滚动方向，1: 向上  2: 向右  3: 向下  4: 向左
    isScrolling:        false,      // 只读，是否正在滚动中
    scrollPeriod:       50,         // 读写，每隔多少毫秒滚动一次，单位为毫秒
    scrollLength:       1,          // 读写，每次滚动的长度，单位为像素
    scrollCount:        0,          // 只读，已滚动的次数
    
    _domNode:           null,       // 用于滚动的页面节点
    _fstChild:          null,       // domNode 的第一套副本
    _secChild:          null,       // domNode 的第二套副本
    _timeoutHandler:    null,       // 持续滚动的句柄
    // 初始化
    // domNode       用于滚动的页面节点或它的 id
    // width         可选，节点宽度，如：100，默认为节点当前的宽度
    // height        可选，节点高度，如：100，默认为节点当前的高度
    _init: function(/*String|DomNode*/ domNode, /*int?*/ width, /*int?*/ height)
    {
        this._domNode = $(domNode);
        this._domNode.style.overflow = "hidden";
        if (width)
        {
            this._domNode.style.width  = width + "px";
        }
        if (height)
        {
            this._domNode.style.height = height + "px";
        }
        // 将 domNode 复制两份
        this._fstChild = this._domNode.cloneNode(true);
        this._fstChild.style.border = "0";
        this._fstChild.style.margin = "0";
        this._fstChild.style.padding = "0";
        this._fstChild.style.overflow = "visible";
        this._secChild = this._domNode.cloneNode(true);
        this._secChild.style.border = "0";
        this._secChild.style.margin = "0";
        this._secChild.style.padding = "0";
        this._secChild.style.overflow = "visible";
        // 改变 this._doScrolling 的上下文
        this._doScrolling = this._doScrolling.hitch(this);
    },
    // 为特定方向的滚动作准备
    // orientation      滚动方向，1: 向上  2: 向右  3: 向下  4: 向左
    _prepare: function(/*int*/ orientation)
    {
        this.orientation = orientation;
        this._fstChild = this._fstChild.cloneNode(true);
        this._secChild = this._secChild.cloneNode(true);
        this._domNode.innerHTML = ""; // 清空 domNode
        if (this.orientation % 2 == 1) // 如果为垂直滚动
        {
            this._domNode.appendChild(this._fstChild);
            this._domNode.appendChild(this._secChild);
        }
        else // 如果为水平滚动
        {
            var table = document.createElement("table");
            table.border = 0;
            table.cellPadding = 0;
            table.cellSpacing = 0;
            table.appendChild(document.createElement("tbody"));
            
            var row = table.insertRow(0);
            var td = row.insertCell(0);
            td.noWrap = true;
            td.appendChild(this._fstChild);
            td = row.insertCell(1);
            td.noWrap = true;
            td.appendChild(this._secChild);
            this._domNode.appendChild(table);
            
            table = null;
            row = null;
            td = null;
        }
    },
    // 滚动一次，返回是否已重新开始移动
    _scroll: function()
    {
        var isRepeat = false;
        switch (this.orientation)
        {
            case 1: // 向上
                if (this._domNode.scrollTop < this._secChild.offsetTop)
                {
                    this._domNode.scrollTop += this.scrollLength;
                }
                else
                {
                    this._domNode.scrollTop = this._secChild.offsetTop - this._fstChild.offsetHeight;
                    isRepeat = true;
                }
                break;
            case 2: // 向右
                if (this._domNode.scrollLeft > (this._secChild.parentNode.offsetWidth - this._fstChild.parentNode.offsetWidth))
                {
                    this._domNode.scrollLeft -= this.scrollLength;
                }
                else
                {
                    this._domNode.scrollLeft = this._secChild.parentNode.offsetWidth;
                    isRepeat = true;
                }
                break;
            case 3: // 向下
                if (this._domNode.scrollTop > (this._secChild.offsetTop - this._fstChild.offsetHeight))
                {
                    this._domNode.scrollTop -= this.scrollLength;
                }
                else
                {
                    this._domNode.scrollTop = this._secChild.offsetTop;
                    isRepeat = true;
                }
                break;
            case 4: // 向左
                if (this._domNode.scrollLeft < this._secChild.parentNode.offsetWidth)
                {
                    this._domNode.scrollLeft += this.scrollLength;
                }
                else
                {
                    this._domNode.scrollLeft = this._secChild.parentNode.offsetWidth - this._fstChild.parentNode.offsetWidth;
                    isRepeat = true;
                }
                break;
        }
        this.onScroll(isRepeat); // 触发 onScroll 事件
        return isRepeat; // Boolean
    },
    /// 开始持续滚动
    // orientation      滚动方向，1: 向上  2: 向右  3: 向下  4: 向左
    // scrollPeriod     可选，每隔多少毫秒滚动一次，默认为 this.scrollPeriod
    // scrollLength     可选，每次滚动的长度，单位为像素，默认为 this.scrollLength
    startScrolling: function(/*int*/ orientation, /*int?*/ scrollPeriod, /*int?*/ scrollLength)
    {
        if (!orientation || orientation < 1 || orientation > 4)
        {
            __apiError("ScrollNode 滚动时参数无效!");
        }
        if (this.isScrolling) // 如果正在持续滚动中
        {
            this.pauseScrolling(); // 暂停持续滚动
        }
        this._prepare(orientation);
        if (scrollPeriod)
        {
            this.scrollPeriod = scrollPeriod;
        }
        if (scrollLength)
        {
            this.scrollLength = scrollLength;
        }
        this.scrollCount = 0;
        this.isScrolling = true;
        this._doScrolling();
    },
    // 持续滚动
    _doScrolling: function()
    {
        if (this.isScrolling)
        {
            this._scroll();
            this.scrollCount++;
            this._timeoutHandler = window.setTimeout(this._doScrolling, this.scrollPeriod);
        }
    },
    /// 暂停持续滚动
    pauseScrolling: function()
    {
        if (this.isScrolling)
        {
            window.clearTimeout(this._timeoutHandler);
            this.isScrolling = false;
            this._timeoutHandler = null;
        }
    },
    /// 继续持续滚动
    continueScrolling: function()
    {
        if (!this.isScrolling)
        {
            this.isScrolling = true;
            this._doScrolling();
        }
    },
    /// 反向持续滚动
    reverseScrolling: function()
    {
        var reverseOrientation = 1;
        switch (this.orientation)
        {
            case 1:
                reverseOrientation = 3;
                break;
            case 2:
                reverseOrientation = 4;
                break;
            case 3:
                reverseOrientation = 1;
                break;
            case 4:
                reverseOrientation = 2;
                break;
        }
        this.orientation = reverseOrientation;
        this.continueScrolling();
    },
    /// 事件，滚动一次后触发，可用于在重新开始移动时，调整滚动的位置和样式
    // isRepeat     是否已重新开始移动
    onScroll: function(/*Boolean*/ isRepeat) {}
};

// 51ditu地图上自定义层的类
// point    显示自定义层的坐标，必须是LTPoint类型
// html     自定义层的html
var __CustomOverLay = function(/*LTPoint*/ point, /*Html*/ html)
{
    this.point = point;
    this.infodiv = document.createElement("div");
    this.infodiv.style.position = "absolute";
    this.infodiv.unselectable = "on";
    this.infodiv.innerHTML = html;
    // this.infodiv.style.zIndex=50;
};
__CustomOverLay.prototype = 
{
    // 在标记被添加到地图(addOverLay)时执行,参数是地图对象
    initialize: function(map)
    {
        // 如果没有创建画圆的层，或者已经被清除，或者已经添加到地图，则直接退出
        if (!this.infodiv || this.map)
        {
            return false;
        } 
        this.map = map;
    },
    // 重绘函数，每次在地图移动的时候执行，如果参数 flag 为 true 代表必须重绘
    reDraw: function(flag)
    {
        // 如果不是必须重绘，则不重绘，大部分的标注都不需要每次重绘
        if (!flag)
        {
            return;
        }
        // 取得 point 左上角的坐标
        var lb = this.map.getOverLayPosition(this.point);
        // 根据左上角坐标设置画圆的位置
        this.infodiv.style.left = lb[0] + "px";
        this.infodiv.style.top = (lb[1] - this.infodiv.clientHeight) + "px";
    },
    // 返回层的函数，返回的层将会被添加到地图之中
    getObject: function()
    {
        return this.infodiv;
    },
    // 在从地图上删除的时候(removeOverLay)被调用
    remove: function()
    {
        this.map = null;
    },
    // 彻底销毁整个控件，节省内存
    depose: function()
    {
        LTEvent.deposeNode(this.infodiv);
        this.infodiv = null;
        this.point = null;
    }
};

/*==数据格式定义==
CenterAndZoom = []
    // 0:       String   x坐标
    // 1:       String   y坐标
    // 2:       int      51ditu中定义的缩放级别，0-14的整数
=====*/
/// 基于51ditu的地图类
// domNode          节点(div)或它的id
// centerAndZoom    可选，地图初始坐标和缩放级别，数据格式见 CenterAndZoom，默认为空
// markCenter       可选，是否标注中心坐标
window.Map = function(/*String|DomNode*/ domNode, /*CenterAndZoom?*/ centerAndZoom, /*Boolean?*/ markCenter)
{
    if (!$(domNode))
    {
        __apiError("创建 Map 对象时具有无效参数!");
        return;
    }
    this._init(domNode, centerAndZoom, markCenter);
};
window.Map.prototype = 
{
    id:             null,   // 只读，该 Map 实例的 id
    domNode:        null,   // 只读，地图节点
    map:            null,   // 只读，对应的 51ditu LTMaps 对象
    zoomBarNode:    null,   // 只读，地图缩放栏节点
    zooms:          [0, 1, 2, 3, 5, 7, 11, 13],     // 只读，缩放级别数组，每项为51ditu 中定义的缩放级别，0-14的整数，从小到大排列
    zoomIndex:      0,      // 只读，当前在缩放级别数组中的位置
    searchControl:  null,   // 只读，地图搜索控件
    companyList:    null,   // 只读，当前地图上的商家列表
    companyIndex:   -1,     // 只读，当前展开了详细信息的商家的位置，未选择时为 -1
    isMarking:      false,  // 只读，是否正在标注
    
    _markOverLay:   null,   // 用于标注的图层
    /*==数据格式定义==
    CenterAndZoom = []
        // 0:       String   x坐标
        // 1:       String   y坐标
        // 2:       int      51ditu中定义的缩放级别，0-14的整数
    =====*/
    // 初始化
    // domNode          节点(div)或它的id
    // centerAndZoom    可选，地图中心坐标和缩放级别，数据格式见 CenterAndZoom，默认为空
    // markCenter       可选，是否标注中心坐标，默认为 false
    _init: function(/*String|DomNode*/ domNode, /*CenterAndZoom?*/ centerAndZoom, /*Boolean?*/ markCenter)
    {
        if (typeof LTMaps == "undefined") // 如果没有引入 51ditu 
        {
            __apiError("没有引入51ditu的js接口");
            return;
        }
        this.id         = getUniqueId("Map");
        this.domNode    = $(domNode);
        this.map        = new LTMaps(this.domNode);  // 初始化地图
        __addMap(this); // 存入全局对象池
//        LTEvent.addListener(this.map, "zoomend", function(){this.changeZoomIndex();}.hitch(this));
        if (centerAndZoom && centerAndZoom[0] && centerAndZoom[1]) // 如果设置了地图中心坐标和缩放级别
        {
            this.locate(centerAndZoom, markCenter);
        }
    },
    
    //=== 地图标注相关 ===//
    
    /*==数据格式定义==
    CenterAndZoom = []
        // 0:       String   x坐标
        // 1:       String   y坐标
        // 2:       int      51ditu中定义的缩放级别，0-14的整数
    =====*/
    /// 定位中心点
    // centerAndZoom    地图中心坐标和缩放级别，数据格式见 CenterAndZoom
    // markCenter       可选，是否标注中心坐标，默认为 false
    locate: function(/*CenterAndZoom*/ centerAndZoom, /*Boolean?*/ markCenter)
    {
        var point = new LTPoint(centerAndZoom[0], centerAndZoom[1]);
        var zoom  = centerAndZoom[2] || this.zooms[this.zoomIndex];
        this.map.centerAndZoom(point, zoom);
        if (markCenter) // 如果需要标注中心坐标
        {
            this.map.addOverLay(new LTMarker(point, new LTIcon("/JsLib/20090331/Images/icon-pao1.gif")));
        }
        if (this.zoomBarNode) // 如果存在缩放栏
        {
            this.changeZoomIndex(); // 重绘地图缩放栏
        }
        point = null;
        zoom = null;
    },
    
    /// 标注或取消标注
    // isMarking    true: 标注   false: 取消标注
    toggleMarking: function(/*Boolean*/ isMarking)
    {
        if (!this._markOverLay)
        {
            this._markOverLay = new LTMarkControl(new LTIcon("/JsLib/20090331/Images/icon-pao1.gif"));
            this._markOverLay.setVisible(false);
            this.map.addControl(this._markOverLay);
            LTEvent.addListener(this._markOverLay,
                                "mouseup",
                                (function(){
                                                var position = this._markOverLay.getMarkControlPoint();
                                                if (!position) // 如果没有点中
                                                {
                                                    this._markOverLay.btnClick();
                                                    this._markOverLay.btnClick();
                                                    return;
                                                }
                                                this.onMarked(position.getLongitude(), position.getLatitude()); // 触发 onMarked 事件
                                                this.isMarking = false;
                                                position = null;
                                            }).hitch(this));
        }
        this.map.clearOverLays();
        if (isMarking != this.isMarking)
        {
            this.isMarking = isMarking;
            this._markOverLay.btnClick();
        }
    },
    
    /// 事件，当标注地图后触发
    onMarked: function(/*String*/ xPosition, /*String*/ yPosition) {},
    
    //=== 地图缩放相关 ===//
    
    /// 初始化地图缩放栏
    // zoomBarNode      地图缩放栏的节点(div)或它的id
    // enableMousewheel 可选，是否允许滚轮滑轮改变地图缩放级别，默认为 false
    // zooms            可选，缩放级别数组，每项为51ditu 中定义的缩放级别，0-14的整数，从小到大排列
    // hasSearchControl 可选，是否包含搜索定位功能
    initZoomBar: function(/*String|DomNode*/ zoomBarNode, /*Boolean?*/ enableMousewheel, /*int[]?*/ zooms, /*Boolean?*/ hasSearchControl)
    {
        this.zoomBarNode = $(zoomBarNode);
        // 设置缩放级别数组
        if (zooms && isArray(zooms))
        {
            this.zooms = zooms;
        }
        // 初始化地图缩放栏
        var id = this.id;
        var html = "";
        html += "<span onclick='$Map(\"" + id + "\").zoomIn();'><img src='/Company/Images/zoomIn.gif' align='absmiddle' border='0' />放大</span>";
        var count = this.zooms.length;
        for (var i = 0; i < count; i++)
        {
            html += "<a id='" + id + "_aZoom" + i.toString() + "'";
            if (i == this.zoomIndex)
            {
                html += " class='current'";
            }
            html += " href='#' onclick='$Map(\"" + id + "\").changeZoomIndex(" + i.toString() + "); return false;'>";
            html += (i + 1).toString();
            html += "</a>";
        }
        html += "<span onclick='$Map(\"" + id + "\").zoomOut()'><img src='/Company/Images/zoomOut.gif' align='absmiddle' border='0' />缩小</span>";
        // 初始化搜索定位控件
        if (hasSearchControl)
        {
            if (typeof LTLocalSearch == "undefined") // 如果没有引入地图搜索 jslib
            {
                __apiError("没有引入51ditu的地图搜索js接口");
                return;
            }
            html += "<input type='text' class='mapKeyword' maxlength='10' /><input type='button' value='定位' onclick='$Map(\"" + id + "\").searchControl.search(this.previousSibling.value.trim());' class='apiButton' />";
            this.searchControl = new LTLocalSearch(function(searchResult)
                                                   {
                                                        if (searchResult.count)
                                                        {
                                                            var theMap = $Map(id);
                                                            var point = searchResult.searchPoints[0].point;
                                                            var currZoom = theMap.map.getCurrentZoom();
                                                            theMap.locate([point[0], point[1], currZoom < 1 ? 1 : (currZoom > 4 ? 4 : currZoom) ]);
                                                            theMap = null;
                                                            point = null;
                                                            currZoom = null;
                                                        }
                                                   });
            var cityId = (getCookie("currentCity") || "=467").split("=")[1];
            this.searchControl.setCity(cityId == 476 ? '绵阳' : '成都');
        }
        this.zoomBarNode.innerHTML = html;
        // 重绘地图缩放栏
        this.changeZoomIndex();
        // 设置滚轮功能
        if (enableMousewheel)
        {
            this.domNode.onmousewheel = this._mousewheel.hitch(this);
        }
        html = null;
        count = null;
        i = null;
    },
    /// 改变地图缩放级别
    // index    可选，在 this.zooms 中的位置，不填时为当前位置
    changeZoomIndex: function(/*int?*/ index)
    {
        // 计算目标缩放级别
        if (typeof index == "undefined")
        {
            index = this._getCurrentIndexOfZooms();
        }
        else
        {
            if (index < 0)
            {
                index = 0;
            }
            if (index > (this.zooms.length - 1))
            {
                index = this.zooms.length - 1;
            }
        }
        // 改变缩放级别
        if (index != this.zoomIndex)
        {
            // 改变选中样式
            removeClass($(this.id + "_aZoom" + this.zoomIndex), "current");
            this.zoomIndex = index;
            addClass($(this.id + "_aZoom" + this.zoomIndex), "current");
            // 缩放地图
            this.map.zoomTo(this.zooms[this.zoomIndex]);
        }
    },
    /// 放大一级别
    zoomIn: function()
    {
        this.changeZoomIndex(this._getCurrentIndexOfZooms() - 1);
    },
    /// 缩小一级别
    zoomOut: function()
    {
        this.changeZoomIndex(this._getCurrentIndexOfZooms() + 1);
    },
    // 获得在缩放级别数组中的位置
    // 51ditu 中定义的缩放级别，0-14的整数
    _getIndexOfZooms: function(/*int*/ zoom)
    {
        for (var i = 0; i < this.zooms.length; i++)
        {
            if (this.zooms[i] == zoom || i == this.zooms.length - 1 || (this.zooms[i] < zoom && this.zooms[i + 1] > zoom))
            {
                return i;
            }
        }
        return 0;
    },
    // 获得当前地图在缩放级别数组中的位置
    _getCurrentIndexOfZooms: function()
    {
        var currZoom = this.map.getCurrentZoom();
        if (typeof currZoom == "undefined")
        {
            return 0;
        }
        return this._getIndexOfZooms(currZoom);
    },
    // 鼠标滚轮控制地图缩放级别的接口
    _mousewheel: function(evt)
    {
        evt = evt || window.event;
        if (evt.wheelDelta)
        {
            evt.wheelDelta > 0 ? this.zoomIn() : this.zoomOut(); 
        }
        return stopEvent(evt);
    },
    
    //===  商家相关 ===//
    
    /*==数据格式定义==
    CompanyInfo = {}
        // id:                 String
        // name:               String
        // imageId:            String
        // browseCount:        String               浏览次数
        // score:              String
        // phone:              String
        // address:            String
        // flag:               String               0 普通商家  1 商铺  2 卖场  3 便民服务  4 连锁店
        // memberFlag:         String               0 不是会员商家  1 是会员商家
        // prepareCount:       String               想去的用户数
        // haveGoneCount:      String               去过的用户数
        // discount:           String               会员商家打折信息或便民服务描述
        // discountInfo:       String               会员商家打折信息
        // xPosition:          String
        // yPosition:          String
        // url                 String               可空，商家的 url
        // overLay:            __CustomOverLay      可空，商家的图层
    =====*/
    /// 在地图上展示多个商家气泡
    /// 如果引入了商家评论模块，则提供商家评论功能
    // companyList  可选，商家数据数组，每项数据格式见 CompanyInfo，为空时，将清除地图上的所有气泡
    // mode         可选，使用第几套模板，1: 大商家信息框  2: 小商家信息框，默认为 1
    markCompanyList: function(/*CompanyInfo[]?*/ companyList, /*int?*/ mode)
    {
        this.map.clearOverLays();
        this.companyList = companyList;
        this.companyIndex = -1;
        if (!companyList || !companyList.length)
        {
            return;
        }
        var points = [];
        for (var i = 0, l = this.companyList.length; i < l; i++)
        {
            var companyOverLay = this._createCompanyOverLay(i, (i + 1).toString(), null, mode);
            this.map.addOverLay(companyOverLay);
            this.companyList[i].overLay = companyOverLay; // 记住商家的图层
            points.push(new LTPoint(this.companyList[i].xPosition, this.companyList[i].yPosition));
        }
        this.map.getBestMap(points); // 以最佳缩放级别显示所有商家气泡
        if (this.zoomBarNode) // 如果存在缩放栏
        {
            // 保证缩放级别不能为最大级别
            var currZoom = this.map.getCurrentZoom();
            if (currZoom == 0)
            {
                this.map.centerAndZoom(this.map.getCenterPoint(), 1); // 无刷新地缩放地图
            }
            this.changeZoomIndex(); // 重绘地图缩放栏
        }
        companyList = null;
        points = null;
        i = null;
        l = null;
        currZoom = null;
        gc();
    },
    // 创建商家图层
    // index        this.companyList 中的位置
    // text         可选，气泡上的文字，默认为空
    // isExpand     可选，是否展开商家详细信息，默认为不展开
    // mode         可选，使用第几套模板，1: 大商家信息框  2: 小商家信息框，默认为 1
    _createCompanyOverLay: function(/*int*/ index, /*String?*/ text, /*Boolean?*/ isExpand, /*int?*/ mode)
    {
        var company = this.companyList[index];
        text = text || '';
        isExpand = !!isExpand;
        company.url = getCompanyUrl(company.id, company.memberFlag); // 记住商家的 url
        
        var aHead = company.url ? '<a href="' + company.url + '" target="_blank" title="' + htmlEncode(company.name) + '">' : '';
        var aTail = company.url ? '</a>' : '';

        var html = '<div class="mappop">';
        html += '<div class="mappoptxt" style="display:' + (isExpand ? '' : 'none') + '" id="' + this.id + '_divCompanyDetail' + company.id + '">';
        if (mode == 2)
        {
            html += '<div class="stop"></div><div class="mid small"><div class="bar">';
            html += '<span class="title">' + aHead + htmlEncode(cutString(company.name, 22)) + aTail;
            if (company.memberFlag == '1') // 如果是会员商家
            {
                html += '&nbsp;<a href="http://card.800lin.com/intro.aspx" target="_blank" title="八佰邻会员商家"><img src="/Company/Images/member.gif" alt="八佰邻会员商家" border="0" align="absmiddle" /></a>';
            }
            html += '</span>';
            html += '<span class="close"><img onclick="$Map(\'' + this.id + '\').onCompanyToggling(' + index + ', false);" src="/JsLib/20090331/Images/mappop-close.gif" /></span></div>';
            if (company.flag == '3') // 如果是便民服务
            {
                html += '<p class="appraise">' + htmlEncode(company.discount) + '</p>';
            }
            else // 如果是普通商家、商铺
            {
                html += '<p class="appraise">';
                var score = toInt(company.score, 2); // 默认评价为 2 星
                for (var j = 1; j < 6; j++)
                {
                    if (j <= score)
                    {
                        html += '<img src="/Company/Images/start.gif" />';
                    }
                    else
                    {
                        html += '<img src="/Company/Images/grayStart.gif" />';
                    }
                }
                var commentCount = toInt(company.prepareCount, 0) + toInt(company.haveGoneCount, 0);
                html += ' ' + company.browseCount + '人浏览，' + commentCount + '人点评</p>';
            }
            if (company.discountInfo)
            {
                html += '<p class="privilege"><img src="/JsLib/20090331/Images/icon-green.gif" align="absmiddle"/> ' + htmlEncode(company.discountInfo) + '</p>';
            }
            html += '<ul class="mapshopInfo"><li>';
            html += '<p class="l">地址：' + htmlEncode(cutString(company.address, 26)) + '<br />电话：' + htmlEncode(cutString(company.phone, 26)) + '</p>';
            html += '<p class="clear"></p></li>';
            if (aTail)
            {
                html += '<li>';
                if (aTail)
                {
                    html += aHead + '查看商铺' + aTail;
                }
                if (CommentOperate) // 如果引入了商家评论模块
                {
                    html += ' | <a href="#" onclick="CommentOperate.showDialog(2, ' + company.id + '); return false;">我去过</a>';
                    html += ' | <a href="#" onclick="CommentOperate.showDialog(1, ' + company.id + '); return false;">我想去</a>';
                }
                html += '&nbsp;</li>';
            }
            html += '</ul></div><div class="sbtm"><div class="arrow"></div></div>';
        }
        else
        {
            html += '<div class="top"></div><div class="mid"><div class="bar">';
            html += '<span class="title">' + aHead + htmlEncode(cutString(company.name, 36)) + aTail;
            if (company.memberFlag == '1') // 如果是会员商家
            {
                html += '&nbsp;<a href="http://card.800lin.com/intro.aspx" target="_blank" title="八佰邻会员商家"><img src="/Company/Images/member.gif" alt="八佰邻会员商家" border="0" align="absmiddle" /></a>';
            }
            html += '</span>';
            html += '<span class="close"><img onclick="$Map(\'' + this.id + '\').onCompanyToggling(' + index + ', false);" src="/JsLib/20090331/Images/mappop-close.gif" /></span></div>';
            if (company.flag == '3') // 如果是便民服务
            {
                html += '<p class="appraise">' + htmlEncode(company.discount) + '</p>';
            }
            else // 如果是普通商家、商铺
            {
                html += '<p class="appraise">评价：';
                var score = toInt(company.score, 2); // 默认评价为 2 星
                for (var j = 1; j < 6; j++)
                {
                    if (j <= score)
                    {
                        html += '<img src="/Company/Images/start.gif" />';
                    }
                    else
                    {
                        html += '<img src="/Company/Images/grayStart.gif" />';
                    }
                }
                var commentCount = toInt(company.prepareCount, 0) + toInt(company.haveGoneCount, 0);
                html += ' ' + company.browseCount + '人浏览，' + commentCount + '人点评</p>';
            }
            if (company.discountInfo)
            {
                html += '<p class="privilege"><img src="/JsLib/20090331/Images/icon-green.gif" align="absmiddle"/> ' + htmlEncode(company.discountInfo) + '</p>';
            }
            html += '<ul class="mapshopInfo"><li>';
            html += '<p class="l">地址：' + htmlEncode(company.address) + ' 电话：' + htmlEncode(company.phone) + '</p>';
            html += '<p class="r"><img src="' + (company.imageId || '0') + '_A80,80,2.dcimg" width="80" height="80"/></p>';
            html += '<p class="clear"></p></li>';
            if (aTail)
            {
                html += '<li>';
                if (aTail)
                {
                    html += aHead + '查看商铺' + aTail;
                }
                if (CommentOperate) // 如果引入了商家评论模块
                {
                    html += ' | <a href="#" onclick="CommentOperate.showDialog(2, ' + company.id + '); return false;">我去过</a>';
                    html += ' | <a href="#" onclick="CommentOperate.showDialog(1, ' + company.id + '); return false;">我想去</a>';
                }
                html += '&nbsp;</li>';
            }
            html += '</ul></div><div class="btm"><div class="arrow"></div></div>';
        }
        html += '</div>';
        html += '<p id="' + this.id + '_pPao' + company.id + '" title="' + htmlEncode(company.name) + '" class="mapPao"';
        html += ' onclick="$Map(\'' + this.id + '\').onCompanyToggling(' + index + ', null);" ';
        html += ' onmouseover="$Map(\'' + this.id + '\').raiseCompany(' + index + ');">' + htmlEncode(text) + '</p>';
        html += '</div>';
        var overLay = new __CustomOverLay(new LTPoint(company.xPosition, company.yPosition), html);
        company = null;
        aHead = null;
        aTail = null;
        html = null;
        j = null;
        commentCount = null;
        
        return overLay;
    },
    /// 上浮某商家的气泡
    // index        this.companyList 中的位置
    raiseCompany: function(/*int*/ index)
    {
        if (this.companyIndex != -1) // 如果已展开了某个商家详细信息
        {
            return;
        }
        if (index < 0 || index >= this.companyList.length)
        {
            __apiError("上浮某商家的气泡时参数无效!");
            return;
        }
        var overLay = this.companyList[index].overLay;
        if (overLay)
        {
            this.map.removeOverLay(overLay);
            this.map.addOverLay(overLay);
        }
        overLay = null;
    },
    /// 事件，当展开或关闭某商家详细信息时触发
    // index        this.companyList 中的位置
    // isExpand     true 为展开，false 为关闭，undefined 或 null 为反向操作
    onCompanyToggling: function(/*int*/ index, /*Boolean*/ isExpand)
    {
        this.toggleCompany(index, isExpand);    // 默认的行为
    },
    /// 展开或关闭某商家详细信息
    // index        this.companyList 中的位置
    // isExpand     true 为展开，false 为关闭，undefined 或 null 为反向操作
    toggleCompany: function(/*int*/ index, /*Boolean?*/ isExpand)
    {
        var company = this.companyList[index];
        var divCompanyDetail = $(this.id + "_divCompanyDetail" + company.id);
        if (divCompanyDetail)
        {
            isExpand = isExpand ? true : (isExpand === false ? false : (divCompanyDetail.style.display == "none" ? true : false));
            if (isExpand) // 如果为展开
            {
                if (this.companyIndex != -1)
                {
                    this.toggleCompany(this.companyIndex, false);
                }
                this.raiseCompany(index);
                divCompanyDetail.style.display = "";
                var pixelCoord = this.map.getPixelCoord(new LTPoint(company.xPosition, company.yPosition));
                this.map.moveToCenter(this.map.getPointLatLng([pixelCoord[0] + 100, pixelCoord[1] - 100])); // 移动到合适位置
                pixelCoord = null;
            }
            else // 如果为关闭
            {
                divCompanyDetail.style.display = "none";
            }
            this.companyIndex = isExpand ? index : -1;
            this.onCompanyToggled(index, isExpand);     // 触发 onCompanyToggled 事件
        }
        company = null;
        divCompanyDetail = null;
    },
    /// 事件，当选择商家后触发
    // index        this.companyList 中的位置
    // isExpand     该商家是否已被选择
    onCompanyToggled: function(/*int*/ index, /*Boolean*/ isExpand) {}
};
// 在全局对象池中存入 Map 对象
function __addMap(/*Map*/ map)
{
    if (map && map instanceof Map)
    {
        addGlobal(map);
    }
}
/// 在全局对象池中获得指定 id 的 Map 对象
// 用 getUniqueId 方法生成的 Map 对象的 id
window.$Map = function(/*String*/ id)
{
    var map = getGlobal(id);
    if (!map || !map instanceof Map)
    {
        __apiError("没有指定的Map对象");
        return null; // null
    }
    return map; // Map
};

/***************************** 基于网站数据和业务的接口 *****************************/
var __alertDialog = new Dialog();
window.oAlert = window.alert;
/// 弹出面向业务的对话框
// content      内容
// title        可选，标题，默认为"温馨提示"
window.alert = function(/*Html*/ content, /*Html?*/ title)
{
    if (__alertDialog.isOpen)
    {
        __alertDialog.close();
    }
    title = title || "温馨提示";
    var html = "";
    html += "<table width='200' border='0' cellpadding='0' cellspacing='0' class='alert'>";
    html += "<tr><td class='alertContent alertTd'>" + content + "<br /></td></tr>";
    html += "<tr><td class='alertTd'><input type='apiPopButton' value='关闭窗口' class='alertCloseButton' onclick='closeAlert();'></td></tr>";
    html += "<tr><td>&nbsp;</td></tr></table>";
    __alertDialog.open(title, html, 200);
};
/// 关闭面向业务的对话框
window.closeAlert = function()
{
    __alertDialog.close();
};
// 登录对话框
var __loginDialog =
{
    id:         getUniqueId(),  // 登录对话框的 id
    dialog:     new Dialog(),   // 登录对话框使用的 Dialog 对象
    vCode:      null,           // 验证码
    // 初始化
    init: function()
    {
        this.open = this.open.hitch(this);
        addGlobal(this); // 存入全局对象池
    },
    // 弹出用户登录对话框
    open: function()
    {
        // 更新验证码
        this.updateVCode(true);
        // 获得上次登录的用户名
        var lastLoginName = this.getLastLoginName();
        // 弹出对话框
        var id = this.id;
        var html = "";
        html += "<div class='loginDialog' onkeydown='if (event.keyCode == 13) getGlobal(\"" + id + "\").login();'>";
        html += "<table width='229' border='0' cellspacing='0' cellpadding='0'>";
        html += "<tr><td class='loginTd' colspan='2'><font color='#3366CC'>您还未登录，请先登录！</font></td>";
        html += "</tr><tr><td class='loginTd' width='49' align='right'>用户名：</td>";
        html += "<td class='loginTd' width='180' align='left'><input type='text' id='loginDialog_txtLoginName' value='" + htmlEncode(lastLoginName) + "' tabIndex='21' class='loginInput' style='width:90px;' maxlength='20'/>";
        html += "<input type='checkbox' id='loginDialog_chkRemember' " + (getCookie("autoLogin") ? "checked" : "") + " /><label for='loginDialog_chkRemember'>自动登录</label></td>";
        html += "</tr><tr><td class='loginTd' align='right'>密　码：</td>";
        html += "<td class='loginTd' align='left'><input type='password' id='loginDialog_txtPassword' tabIndex='22' class='loginInput' style='width:155px;' maxlength='16'/></td>";
        html += "</tr><tr><td class='loginTd' align='right'>验证码：</td><td class='loginTd' align='left'>";
        html += "<input type='text' id='loginDialog_txtVCode' tabIndex='23' class='loginInput' style='width:55px;' maxlength='5'/>&nbsp;";
        html += "<img id='loginDialog_imgVCode' src='/CommonPages/ShowValidationCodePic.aspx?rid=" + this.vCode + "' onclick='getGlobal(\"" + id + "\").updateVCode();' style='cursor:pointer;' height='20' width='50' align='absmiddle'/>&nbsp;";
        html += "<a href='#' onclick='getGlobal(\"" + id + "\").updateVCode(true); return false;'>看不清楚</a>";
        html += "</td></tr><tr><td class='loginTd'>&nbsp;</td>";
        html += "<td class='loginTd'><input type='button' onclick='getGlobal(\"" + id + "\").login()' class='apiButton' tabIndex='24' value='登录'/>&nbsp;";
        html += "<input type='button' onclick='window.location.href=\"http://www.800lin.com/register.aspx\"' class='apiButton' value='我要注册'/></td>";
        html += "</tr></table></div>";
        this.dialog.open("用户登录", html, 330);
    },
    // 登录
    login: function()
    {
        var loginName  = $("loginDialog_txtLoginName").value;
        var password   = $("loginDialog_txtPassword").value;
        var vCode = $("loginDialog_txtVCode").value;
        
        if (loginName.trim() == "")
        {
            alert("请输入用户名");
            return;
        }
        if (password == "")
        {
            alert("请输入密码");
            return;
        }
        if (vCode == "")
        {
            alert("请输入验证码");
            return;
        }
        if (vCode != this.vCode)
        {
            alert("您输入的验证码不正确，请重新输入");
            this.updateVCode();
            return;
        }
        var response = xhrPost({
                                   url:         "/Common/Handlers/CommonHandler.ashx?funcname=userLogin",
                                   sync:        true,
                                   content:     {
                                                    name:           loginName,
                                                    password:       password,
                                                    autoLogin:      $("loginDialog_chkRemember").checked ? 1 : 0,
                                                    type:           0
                                                }
                              });
        if (response)
        {
            if(response == "-3") // 没有被激活  段建伟 20090721 16：32
            {
                if(confirm("您的账号还没有被激活，是否现在去激活？"))
                {
                    window.location.href="http://www.800lin.com/active_2.aspx?userInfo=" + loginName  ;
                }
            }
            else
            {
                // 触发 onSuccess 事件
                this.dialog.close();
                this.setLastLoginName(loginName); // 记住用户名
                this.onSuccess();
            }
        }
        else
        {
            alert("用户名或密码不正确");
        }
        loginName = null;
        password = null;
        vCode = null;
        response = null;
    },
    // 更新验证码
    // lateRender       是否延迟显示验证码
    updateVCode: function(/*Boolean*/ lateRender)
    {
        this.vCode = xhrPost("/Common/Handlers/CommonHandler.ashx?funcname=getVCode");
        if ($("loginDialog_imgVCode"))
        {
            var uri = "/CommonPages/ShowValidationCodePic.aspx?rid=" + this.vCode;
            if (lateRender)
            {
                preLoadImage(uri);
                window.setTimeout("$('loginDialog_imgVCode').src = '" + uri + "';", 500);
            }
            else
            {
                $("loginDialog_imgVCode").src = uri;
            }
        }
    },
    // 记住上次登录的用户名，返回是否成功
    // userName     上次登录的用户名
    setLastLoginName: function(/*String*/ userName)
    {
        if (!userName || !isString(userName) || !userName.trim())
        {
            return false; // Boolean
        }
        xhrPost({
                    url:        "/HomePage/Handlers/MasterHandler.ashx?funcName=RemberLastUser",
                    content:    {
                                    name:   userName.trim()
                                },
                    sync:       false
               });
        return true; // Boolean
    },
    // 清除上次登录的用户名
    removeLastLoginName: function()
    {
        xhrPost("/HomePage/Handlers/MasterHandler.ashx?funcName=clearLastUser");
    },
    // 获取上次登录的用户名
    getLastLoginName: function()
    {
        return xhrPost("/HomePage/Handlers/MasterHandler.ashx?funcName=getRemberLastUser"); // String
    },
    // 事件，登录成功后触发
    onSuccess: function() {}
};
__loginDialog.init();

/// 用户登录
// 注意：在 IE6 下，使用 a 标签的 href 或 onclick 时，页面如果未加载完将停止加载。
// url          可选，登录成功后跳转到的地址，默认为刷新本页面
// onSuccess    可选，登录成功后的处理方法，默认为刷新或跳转页面
window.login = function(/*Url?*/ url, /*Function?*/ onSuccess)
{
    if (__loginDialog.dialog.isOpen)
    {
        return;
    }
    // 设置登录成功的事件处理方法
    if (!onSuccess)
    {
        // 默认的登录成功的事件处理方法
        onSuccess = function ()
                         {
                              if (url)
                              {
                                  window.location.href = url; // 跳转地址
                              }
                              else
                              {
                                  window.location.reload(); // 刷新本页面
                              }
                         }
    }
    __loginDialog.onSuccess = onSuccess;
    // 弹出登录对话框
    __loginDialog.open();
};
/// 注销登录，返回是否成功
// url          可选，注销后跳转到的地址，默认刷新本页面
// onSuccess    可选，注销后的处理方法，默认为跳转页面
window.logout = function(/*Url?*/ url, /*Function?*/ onSuccess)
{
    var response = xhrGet("/HomePage/Handlers/MasterHandler.ashx?funcName=LogOut");
    if (response == "1")
    {
        if (onSuccess)
        {
            onSuccess();
        }
        else
        {
            if (url)
            {
                window.location.href = url; // 跳转地址
            }
            else
            {
                window.location.reload(); // 刷新本页面
            }
        }
        return true; // Boolean
    }
    else
    {
        return false; // Boolean
    }
    response = null;
};
/// 获得商家的地址
// id               商家id
// memberFlag       0 普通商家  1 会员商家
window.getCompanyUrl = function(/*int|String*/ id, /*int|String*/ memberFlag)
{
    if (memberFlag.toString() == "1")
    {
        return "http://www.800lin.com/shop/" + id + ".aspx";
    }
    else
    {
        return "http://www.800lin.com/shop/detail/" + id + ".aspx";
    }
};
/// 发送 800Q 消息
// userId   消息接收者的id
// message  消息内容
window.send800QMessage = function(/*int*/ userId, /*Html*/ message)
{
    if (!userId)
    {
        __apiError("发送 800Q 消息时参数无效");
        return;
    }
    if (!message || !isString(message) || !stripTags(message).trim())
    {
        alert("请输入消息内容");
        return;
    }
    xhrPost({
                url:        "/800QNew/Handlers/800QHandler.ashx?funcname=SendMessage&receiver=" + userId,
                sync:       false,
                content:    {
                                message:    message
                            }
           })
};
/// 向个人或者家庭发送消息，返回是否成功
// id               个人或家庭的 id
// type             1 表示个人，2 表示家庭
window.sendMessage = function(/*int|String*/ id, /*int*/ type, /*Html*/ content)
{
    if (!content || !htmlDecode(content).trim())
    {
        alert("请输入内容！") ;
        return false;
    }
    if (type == 1) // 如果发送给个人
    {
        send800QMessage(id, content); // 发送 800Q 消息
        return true;
    }
    else // 如果发送给家庭
    {
        // 发送站内信
        var response = xhrPost({
                                   url:         "/Common/Handlers/CommonHandler.ashx?funcname=sayHello",
                                   sync:        true,               
                                   content:     {
                                                    reciveUsers:    "",
                                                    reciveFamilys:  id,
                                                    content:        content
                                                }
                              });
        response = xmlToObject(response);
        var result = response.result;
        if (result == "1")
        {
            response = null;
            result = null;
            return true;
        }
        else
        {
            response = null;
            result = null;
            return false;
        }
   }
};
/// 加为好友，返回是否成功
// id               个人或家庭的 id
// type             1 表示个人，2 表示家庭
// content          附加信息
// friendGroupId    个人或家庭的好友分组 id
window.beFriend = function(/*int|String*/ id, /*int*/ type, /*Html*/ content, /*int|String*/ friendGroupId)
{
    var response = xhrPost({
                               url:         "/Common/Handlers/CommonHandler.ashx?funcname=beFriend",
                               sync:        true,
                               content:     {
                                                targets:    id,
                                                type:       type,
                                                content:    content,
                                                group:      friendGroupId
                                            }
                          });
    switch (response)
    {
        case "1":
            alert("消息已经发出，请等待对方确认");
            return true;
            break;
        case "-2":
            alert("Ta 已经是您的好友了");
            return false;
            break;
        case "-3":
            alert("不能加自己为好友");
            return false;
            break;
        default:
            alert("操作失败！");
            return false;
            break;            
    }
};
/// 邀请个人加入圈子，返回是否成功
// userId   所邀请的用户 id
// groupId  所邀请到的圈子 id
window.goToGroup = function(/*int|String*/ userId, /*int|String*/ groupId)
{
    var response = xhrGet({
                               url:     "/Common/Handlers/CommonHandler.ashx?funcname=insertGroupInterestMemberInvite",
                               sync:    true,
                               content: {
                                            memberId:   userId,
                                            groupId:    groupId,
                                            content:    "",
                                            role:       3
                                        }
                         });
    switch (response)
    {
        case "1":
            alert("邀请函已发出");
            return true;
            break;
        case "-2":
            alert("Ta 已经加入了该圈子");
            return false;
            break;
        default:
            alert("操作失败！");
            return false;
            break;
    }
};
/// 获取用户的 Html
// userId       用户id
window.getUserHTML = function(/*int*/ userId)
{
    return xhrGet({url: "/Common/Handlers/CommonHandler.ashx?funcname=getUserHTML&domain=&userId=" + userId});
};
/// 获取家庭的 Html
// familyId     家庭id
window.getFamilyHTML = function(/*int*/ familyId)
{
    return xhrGet({url: "/Common/Handlers/CommonHandler.ashx?funcname=getFamilyHTML&domain=&familyId=" + familyId});
};
// 面向业务的提示框类
function __ToolTipControl()
{
    var tooltip = new Tooltip();
    var currentObj;        // 当前实例
    var isShow = false;    // 是否已经有窗口弹出
    var timerToolTip;      // 打开窗口定时器
    var timerClose;        // 关闭窗口定时器
    var func;              // 获取展示数据的方法名字符串
    var currentParamiter;  // 参数字符串 
    var instance = "";     // 被初始化的对象字符串
    var guardTime = 1500;  // 警戒时间
    var showTime = 5000;   // 无操作显示时间
    // 初始化参数
    //_func 获取展示数据的函数名字符串
    //_instance 被初始化的对象字符串
    //_guardTime 警戒时间 默认为1500毫秒
    //_showTime 无操作显示时间 默认为2000毫秒
    this.load = function(_func, _instance, _guardTime, _showTime)
    {
        func = _func;
        instance = _instance;
        if(_guardTime != null)
        {
            guardTime = _guardTime;
        }
        if(_showTime != null)
        {
            showTime = _showTime;
        }
    };
    
    //开始警戒 用于onmouseover 事件
    //obj 当前控键对象
    //paraStr 参数字符串
    this.guard = function(obj,paraStr)
    {
       /* if(instance == "userToolTip" && paraStr == 100)return;//系统帐号不进行任何处理
        
        if(isShow && currentObj != obj)
        {
            isShow = false;
            dijit.hideTooltip(currentObj);               
        }
        
        currentObj = obj;
        currentParamiter = paraStr;
        timerToolTip = setTimeout(_show,guardTime)*/
    };
    
    //显示
    var _show = function()
    {           
        _focus();
        isShow = true;
        var _strHTML = eval(func + "(\""+currentParamiter+"\")");
        
        //_strHTML = "<div style=\"width:303px\" onmouseover=\"" +instance + ".focus()\" onmouseout=\"" +instance + ".onfocus()\">"+_strHTML+"</div>";
    
        tooltip.show(currentObj, _strHTML);
        
        timerClose = window.setTimeout(_close, showTime);
    };
    
    //直接显示窗口 用于onclick 事件等
    //obj 当前控键对象
    //paraStr 参数字符串
    this.show = function(obj,paraStr)
    {
        if(instance == "userToolTip" && paraStr == 100)return;//系统帐号不进行任何处理
        if(isShow && currentObj == obj)return;
        
        if(isShow && currentObj != obj)
        {
            isShow = false;
            tooltip.close();               
        }  
        
        currentObj = obj;
        currentParamiter = paraStr;
        _show();
    };
    
    //关闭显示窗口
    this.close = function()
    {
        _close();
    };
    
    var _close = function()
    {
        if(isShow)
        {
            tooltip.close();
            window.clearInterval(timerToolTip);
            isShow = false;
        }
    };
    
    //关闭定时器 用于onmouseout 事件
    this.clear = function()
    {
       /* if(timerToolTip != null)
        {
            clearInterval(timerToolTip);
        }
        timerToolTip = null; */
    };
    
    var _focus = function()
    {
       if(timerClose != null)
       {
            clearInterval(timerClose);
            timerClose = null; 
       }
    };
    
    this.focus = function()
    {
        _focus();
    };
    
    this.onfocus = function()
    {
        timerClose = setTimeout(_close,showTime);
    };
    
    //弹出发送消息的窗口
    this.openNewWindow = function(index, type)
    {  
        switch(index)
        {
            case 1:            
                _openMessageWindow(type);
                break;
            case 2:
                _openBeFriendWindow(type);
                break; 
            case 3:
                _openGoToGroup(type);
                break;
        }
       
    };
    
    var _openGoToGroup = function(type)
    {
        xhrPost({
                   url:     "/Common/Handlers/CommonHandler.ashx?funcname=getGroup",
                   sync:    false,
                   load:    _openGoToGroupSuc,     
                   content: {type: type}
               });
    };
    
    var _openGoToGroupSuc = function(strXML)
    {
        var data = xmlToObject(strXML, "group");
        var flag = data.flag;
        if (flag == "0")
        {
            login();
            return;
        }
        
        var type = parseInt(data.type);
        var groups = data.groups.groupList;
        
        var str = ""; 
        str += "<table style=\"text-align:left;width:200px\" width=\"200\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">";
        /*str += "<tr>";
        str += "  <td height=\"22\" valign=\"middle\">附加消息：</td>";
        str += "</tr>";
        str += "<tr>";
        str += "  <td><textarea id=\"txtMessageContent\" cols=\"17\" rows=\"3\"></textarea></td>";
        str += "</tr>";*/
        str += "<tr>";
        str += "  <td height=\"22\" valign=\"middle\">选择圈子：<select id=\"sltFriendGroup\">";
        if (groups && groups.length)
        {
            for(var i=0;i<groups.length;i++)
            {
                var id = groups[i].id;
                var name = groups[i].name;           
                str += "<option value=\""+id+"\">"+htmlEncode(name)+"</option>";
            }
        }
        str += "</select></td>";
        str += "</tr>";
        str += "<tr>";
        str += "  <td height=\"35\" valign=\"middle\"><input type=\"button\" onclick=\"goToGroup(" + currentParamiter + ", $('sltFriendGroup').value);" + instance + ".close();\" class=\"seabtn\" value=\"发送\"/>";
        str += "      &nbsp;&nbsp;<input type=\"button\" onclick=\""+instance+".close()\" class=\"seabtn\" value=\"取消\"/></td>";
        str += "</tr>";
        str += "</table>";
         _close();
        tooltip.show(currentObj, str);
        
        gc();
    };
    
    var _openMessageWindow = function(type)
    {
       xhrPost({
                   url:     "/Common/Handlers/CommonHandler.ashx?funcname=getUserIsOnline",
                   sync:    false,
                   load:    _openMessageWindowSuc,   
                   content: {type:type}
              });
    };
    
    var _openMessageWindowSuc = function(strXML)
    {
        var data = xmlToObject(strXML);
        
        var type = parseInt(data.type);
        var flag = data.flag;
        
        if (flag != "0")
        {
            var str = ""; 
            str += "<table style=\"text-align:left;width:200px\" width=\"200\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">";
           /* str += "    <tr>";
            str += "      <td width=\"39\" height=\"33\">标题：</td>";
            str += "      <td width=\"161\"><input id=\"txtMessageTitle\" type=\"text\" class=\"textbox\" size=\"18\"/></td>";
            str += "    </tr>";*/
            str += "    <tr>";
            str += "      <td height=\"48\" valign=\"top\">内容：</td>";
            str += "      <td valign=\"top\"><textarea id=\"txtMessageContent\" cols=\"17\" rows=\"3\"></textarea></td>";
            str += "    </tr>";
            str += "    <tr>";
            str += "      <td height=\"30\">&nbsp;</td>";
            str += "      <td><input type=\"button\" class=\"seabtn\" onclick=\"if (!sendMessage(" + currentParamiter + ", " + type + ", textAreaValueToHtml($('txtMessageContent').value))) alert('发送消息失败');" + instance + ".close()\" value=\"发送\"/>";
            str += "           &nbsp;&nbsp;<input type=\"button\" onclick=\""+instance+".close()\" class=\"seabtn\" value=\"取消\"/></td>";
            str += "    </tr>";
            str += "  </table>";
             _close();
            tooltip.show(currentObj, str);
        }
        else
        {
            login();
        }
        
        gc();
    };
    
    var _openBeFriendWindow = function(type)
    {
        var familyId = -1 ;
        if (top.gFamilyId)
        {
            familyId = top.gFamilyId;
        }
        xhrPost({
                   url:     "/Common/Handlers/CommonHandler.ashx?funcname=getFriendGroup&familyId=" + familyId,
                   sync:    false,
                   load:    _openBeFriendWindowSuc,   
                   content: {type:type}
               });
    };
    
    var _openBeFriendWindowSuc = function(strXML)
    {
        var data = xmlToObject(strXML, "group");
        var flag = data.flag;
        if (flag == "0")
        {
            login();
            return;
        }
        
        var type = parseInt(data.type);
        var groups = data.groups.groupList;
        var str = ""; 
        str += "<table style=\"text-align:left;width:200px\" width=\"200\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">";
        str += "<tr>";
        str += "  <td height=\"22\" valign=\"middle\">附加消息：</td>";
        str += "</tr>";
        str += "<tr>";
        str += "  <td><textarea id=\"txtMessageContent\" cols=\"17\" rows=\"3\"></textarea></td>";
        str += "</tr>";
        str += "<tr style=\"display:none\">";
        str += "  <td height=\"22\" valign=\"middle\">选择分类：<select id=\"sltFriendGroup\">";
        if (groups && groups.length)
        {
            for(var i=0;i<groups.length;i++)
            {
                var id = groups[i].id;
                var name = groups[i].name;
                if(i == 0)
                {
                    str += "<option value=\""+id+"\" selected>"+htmlEncode(name)+"</option>";
                }
                else
                {
                    str += "<option value=\""+id+"\">"+htmlEncode(name)+"</option>";
                }
            }
        }
        str += "</select></td>";
        str += "</tr>";
        str += "<tr>";
        str += "  <td height=\"35\" valign=\"middle\"><input type=\"button\" onclick=\"beFriend(" + currentParamiter + ", " + type + ", textAreaValueToHtml($('txtMessageContent').value), $('sltFriendGroup').value);" + instance + ".close();\" class=\"seabtn\" value=\"发送\"/>";
        str += "      &nbsp;&nbsp;<input type=\"button\" onclick=\""+instance+".close()\" class=\"seabtn\" value=\"取消\"/></td>";
        str += "</tr>";
        str += "</table>";
         _close();
        tooltip.show(currentObj, str);
        
        gc(); 
    };
    
    
    /// 关闭提示框
    this.close = function()
    {        
        tooltip.close(); 
    };
    
    //发送消息
    //obj 指定弹出的对象
    //paraStr 个人或者家庭编号
    //type 1个人，2家庭
    this.sendMessage = function(obj,paraStr,type)
    {   
        currentObj = obj;
        currentParamiter = paraStr;
        _openMessageWindow(type);
    };
    
    //加为好友
    //obj 指定弹出的对象
    //paraStr 个人或者家庭编号
    //type 1个人，2家庭
    this.beFriend = function(obj,paraStr,type)
    {    
        currentObj = obj;
        currentParamiter = paraStr;
        _openBeFriendWindow(type);
    };
    
    //邀请加入圈子
    //obj 指定弹出的对象
    //paraStr 个人编号
    this.goToGroup = function(obj,paraStr)
    {
        currentObj = obj;
        currentParamiter = paraStr;
        _openGoToGroup(1);
    };
};
/// 用户信息框，用法如下：
// <a href='#' onclick='userToolTip.show(this, userId); return false;'>用户名</a>
// userId       用户id
window.userToolTip = new __ToolTipControl();
window.userToolTip.load("getUserHTML", "userToolTip");
/// 家庭信息框，用法如下：
// <a href='#' onclick='familyToolTip.show(this, familyId); return false;'>家庭名</a>
// familyId     家庭id
window.familyToolTip = new __ToolTipControl();
window.familyToolTip.load("getFamilyHTML", "familyToolTip");
/// 打招呼提示框，用法如下：
// <a href='#' onclick='sendMessageToolTip.sendMessage(this, userId, 1); return false;'>向个人打招呼</a>
// <a href='#' onclick='sendMessageToolTip.sendMessage(this, familyId, 2); return false;'>向家庭打招呼</a>
// userId       用户id
// familyId     家庭id
window.sendMessageToolTip = new __ToolTipControl();
window.sendMessageToolTip.load("", "sendMessageToolTip");
/// 加为好友提示框，用法如下：
// <a href='#' onclick='beFriendToolTip.beFriend(this, userId, 1); return false;'>加个人为好友</a>
// <a href='#' onclick='beFriendToolTip.beFriend(this, familyId, 2); return false;'>加家庭为好友</a>
// userId       用户id
// familyId     家庭id
window.beFriendToolTip = new __ToolTipControl();
window.beFriendToolTip.load("", "beFriendToolTip");
/// 邀请加入圈子提示框，用法如下：
// <a href='#' onclick='goToGroupToolTip.goToGroup(this, userId); return false;'>邀请加入我的圈子</a>
// userId       用户id
window.goToGroupToolTip = new __ToolTipControl();
window.goToGroupToolTip.load("", "goToGroupToolTip");

/// 举报接口
var __AddComplaint = function()
{
    var mUrl = "";
    var mObj =  "";
    var mEntity = "";
    var mTitle = "";
    var mResourceId = 0;
    var mModule = "";
    var mSuspecter = 0;
    var mTip = "";
    /// 添加举报
    // url          资源url
    // obj          对象
    // title        举报标题
    // resource_id  资源id
    // module       资源所属的模块的枚举名  ResourceTypeEnum
    // suspecter    被举报人
    // tip          可选，默认的举报理由
    this.load = function(/*Url*/ url, /*DomNode*/ obj, /*Html*/ title, /*int|String*/ resouce_id, /*String*/ module, /*int|String*/ suspecter, /*String?*/ tip)
    {
        mUrl = url;
        mObj =  obj;
        mTitle = title;
        mResourceId = resouce_id;
        mModule = module;
        mSuspecter = suspecter;
        mEntity = "addComplaint";
        
        if(tip != null)//韩威添加
        {
            mTip = tip;
        }
        
        //获取当前登录用户加入的所有家庭，并创建收藏弹出窗口

        mEntity = encodeURIComponent(mEntity); 
        var url1 = "/Common/Handlers/CommonHandler.ashx?funcname=initComplaintInterfaceDivPage";
        xhrGet({
               url: url1,
               load: CreateDivSuc,
               sync: false,
               content:{resouceUrl:mUrl,entity:mEntity}
            }); 
    };
    function CreateDivSuc(response)
    {
        if(response == "-1")
        {
            alert("您还没有创建家庭，请先创建一个家庭吧!");
            return; 
        } 
       if(response == "0")
       {
            login();
            return; 
       } 
       else
       {
            closeTooltip();
            showTooltip(mObj,response);  
            $("txtComplaintReson").value = mTip; 
       } 
    };
    this.CancelInter = function()
    {
        closeTooltip();
    };

    this.saveComplaint = function()
    {
        var mContent =  $("txtComplaintReson").value;
        if(mContent.trim() == "")
        {
            alert("请填写举报内容!");
            return;
        }  
        if(mContent.length>=200)
        {
            alert("内容过长!");
            return;
        }
        
        mContent = encodeURIComponent(mContent.trim());
        var url = encodeURIComponent($("txtComplaintUrl").value);
        
        var mGetUrl = "/Common/Handlers/CommonHandler.ashx?funcname=saveComplaint&resouceUrl="+url+"&reason="+mContent+
            "&resouceId="+encodeURIComponent(mResourceId) + "&module="+mModule+
            "&title="+encodeURIComponent(mTitle)+"&suspecter="+mSuspecter;
        
        xhrGet({
                   url: mGetUrl,
                   sync: false,
                   load: SaveInterComplatintSuc                
                }); 
   };
   function SaveInterComplatintSuc(response)
   {
        var re = response;
        if(re == "1")
        {
            alert("举报已发送!");
            //this.CancelInter();
             closeTooltip();
        } 
       else
       {
            alert("举报失败!");
       }  
   };
};
window.addComplaint = new __AddComplaint();

})();   // 单调方法结束
