///<jscompress sourcefile="Main.js" />


//朱艳萍老师建议:用释义的方式更加利于学生理解,也更加便于此系统的普及及应用,建议采纳。
//Usestudio.UnionForm.getUserLocation
//U.UF.CI.getUserLocation = function (fun) {


/*
变量命名编写规范:
变量类型   变量名称
string       str
object       obj。
Array        arr
Element      el
bool         b
用户信息     userinfo
硬盘信息     diskinfo
好友信息     frindinfo
群信息       groupinfo
回调callback       cb
函数         fun
错误         err
参数数组aruguments   arg    
*/
/*
uform框架解决了以下问题:
1、此js主要扩展了String,Number,Array,Object,Guid,json,Date等七种数据类型的方法,还有一些html5的数据类型,但暂未使用,此js需要立即执行的区域比较多。
2、有丰富的正则表达式
3、为了对元素进行更良好的操作,如动画,选择元素,制作了选择器
4、全兼容ie6以上浏览器,Chrome浏览器,Safari浏览器,Firefox。
*/

//#region document.domain 设置区域

//域名初始化 这个地方是初始化domain 设置后允许跨域
//用于
try {
    if (document.domain) {
        //如果是1473的域名。
        if (document.domain.indexOf("1473.cn") > -1) {
            document.domain = "1473.cn"; //把www.1473.cn和main.1473.cn,a.1473.cn的域统一设置为1473.cn
        }
        else {
            document.domain = "boomyun.com"; //是能是boomyun.com有效,其他均不能设置,会跳转到catch语句
        }
    }
}
catch (e) { }

//#endregion

//#region 命名空间处理

//命名空间类
window.Namespace = {};

/**
* 命名空间注册
*
* @param  {object} 好友头像处理
* @param  {object} 方法集合
* @param  {function} 注册时候的回调函数
* @return  {object} 命名空间
*/
Namespace.register = function (namespace) {
    var i,
        _local = window, //用于把第一个命名空间归属于window。
        _namespacearr = namespace.split("."); //命名空间分段
    //循环命名空间变量定义区域
    for (i = 0; i < _namespacearr.length; i++) {
        //如果命名空间未定义,那么给该命名空间添加方法
        if (!_local[_namespacearr[i]]) {
            _local[_namespacearr[i]] = {}; //创建一个新的命名空间
        }
        //由于命名空间的方式为 name.name.name 每一次会循环.号后面的,所以每一次等于创建命名空间的值
        _local = _local[_namespacearr[i]];
    }
}

//#endregion

//#region uform云端全局变量处理区域
Namespace.register("U"); //注册全局函数命名空间
Namespace.register("US"); //注册全局变量命名空间
if (!US.disk) {
    //变量定义区域
    US.userInfo = {}; //个人用户变量
    US.disk = {}; //网盘使用变量
    US.blog = {}; //朋友圈变量
    US.forum = {}; //学习系统
    US.friend = {}; //用户好友
    US.city = {}; //系统访问用户信息
    //此处为1473常用全局变量
    US.domain = "1473.cn"; //主站点命名
    US.forum.news = null; //论坛消息
    US.systemId = 0; ////默认为0,作为测试用使用,1为1473主站用,2为1473手机端用。
    US.pageId = ""; //页面识别码,用户通过浏览器进入生成唯一识别码,解决同一个浏览器多登录情况下,及聊天室刷新功能。
    //US.userInfo.LoginId  这个是用户登录识别码,记录在Cookie中,并在后台识别,保证是同一个用户进行操作。
    US.height = window.screen.availHeight; //页面高度
    US.width = window.screen.availWidth; //页面长度

    //常量定义区域
    US.OFFICEFILEURL = "http://office.1473.cn/usoffice/"; //office 打开文件对应链接
    US.SCOKET = "http://poll.1473.cn"; //1473长轮训 长连接请求地址
    US.FILESYSTEMURL = "http://fs.1473.cn/";  //fs对应的链接
    US.DOMAIN = "http://www.1473.cn/"; //主站域名
    US.ERRORIMAGE = "http://www.1473.cn/img/error.png"; //错误图片
    US.CD = "http://cd.1473.cn/net/ssh.ashx"; //请求地址
    US.AUTH = "http://main.1473.cn/Uses.ashx"; //请求地址
    US.FRIEND = "http://friend.1473.cn/friend.ashx"; //请求地址
    US.DISK = "http://disk.1473.cn/disk.ashx"; //请求地址
    US.USER = "http://user.1473.cn/user.ashx"; //请求地址
    US.ADMINAUTH = "http://main.1473.cn/admin.ashx"; //请求地址
    US.DB = "sqlserver.1473.cn"; //1473数据库的地址
    US.FORUMROOTID = "1e0742d8-737e-46e2-b03b-2f23ca8c1f17"; //论坛根目录id
    US.MYDISK = "d8ae0266-481d-4064-86d2-fb52a4059793";  //我的电脑id
    US.PRIVATEFOLDERID = "9639aba6-03eb-443c-be4e-f0c8d24767f5"; //私密文件夹id
    US.FTPFOLDERID = "f6d7a4b6-e34c-4964-beed-24187b2cb1ba"; //FTP文件夹id
    US.MYFOLDERID = "7aeaab56-485f-4150-b781-8ffd86d593ce"; //我的文件夹id
    US.IMAGEFOLDERID = "93553847-e299-464c-a0e2-c15872efb6ae"; //图片文件夹id
    US.MUSICEFOLDERID = "8a2135ff-746a-43a8-97b8-552d228a00bb"; //我的音乐文件夹id
    US.VIDEOFOLDERID = "bf21bf7a-1e95-4194-8e4a-e9334d7d998d"; //视频文件夹id
    US.EMPTYGUID = "00000000-0000-0000-0000-000000000000"; //空id
    US.ZINDEX = 20;  //页面层次
    US.FEEDBACKID = "3c779543-bc1a-4851-af22-af9ba97a5f33" //意见反馈目录id;
    US.MAINDOMAIN = "http://" + ((window.location.host.indexOf("www.1473.cn") > -1 ||
                 window.location.host == "1473.cn" ||
                 window.location.host.indexOf("www.boomyun.com") > -1 ||
                 window.location.host == "boomyun.com") ? window.location.host : "www.1473.cn");
}
//#endregion
;
///<jscompress sourcefile="Ajax.js" />
/*
此函数为ajax区域 要求所有后台请求来自于这里
应该5秒内返回给用户一个提示信息。涉及到提示信息可以传递时间参数到此ajax,如果5秒未收到结果,则弹出重试的提示。
ajax 跨域有问题 没有到回调里面去
*/
/*
变量命名编写规范:
变量类型   变量名称
string       str
object       obj。
Array        arr
Element      el
bool         b
用户信息     userinfo
硬盘信息     diskinfo
好友信息     frindinfo
群信息       groupinfo
回调callback       cb
函数         fun
错误         err
参数数组aruguments   arg    
*/

//补充错误的定义。
//错误状态写在r.request.status里面。如果r.request.status==200,则表示成功。其余状态码表示有错误,如果是我们系统发生错误,统一状态码为500,即r.request.status==500,其他由web服务器自己决定。
//详细错误信息在r.value里面.




Namespace.register("U.A"); //A为Ajax简写

//所有请求的ajax对象.
U.A.allAjaxRequest =
{
    requestNumber: 0, //总共请求次数
    requestObject: [], //请求的所有ajax对象
    forrequest: 0 //可能存在的循环请求的次数
};


//服务器返回值结构图
/*_returnobj = { //返回的ajax对象
httpRequest: ajaxobject,  //xmlrequest对象
status: 200,  //服务器响应的状态 200成功,其他的都是失败
value: null, //服务器返回的值
context: cbparams //回调函数的参数
};*/


//开发后端程序时需要返回的结构体
var serverInfo = {
    affectRows: null,  //数据库影响行数,插入,修改,删除时,如果大于0,表示成功,否则,表示失败
    value: null, //数据库查询时的取值。如果错误,请查看其他变量的值
    error: null,  //数据库及服务器错误信息
    statusCode: null  //服务器状态码,服务器响应的状态 200成功,其他的都是失败
}

//uform前端ajax返回值结构体
var serverReturnObj = { //返回的ajax对象
    httpRequest: null,  //xmlrequest对象,前台标准
    status: 200,  //服务器响应的状态 200成功,其他的都是失败,,这是历史遗留,以后要删除
    serverInfo: serverInfo, //等于后端结构体
    value: null, //服务器返回的值,历史遗留,以后删除
    context: null //回调函数的参数,前台标准
};


//#region ajax

/**
* ajax初始化区域
*
* @param  {string} 访问的地址
* @param  {array} 数据库地址,数据库名,存储过程名,存储过程参数的数组
* @param  {function} 回调函数
* @param  {array} 函数传参
* @param  {object} 需要写入的header对象
* @returns {object} ajax对象 
*/
U.A.Request = function (url, params, cb, cbparams, header) {
    //判断是否为攻击
    if (U.A.Request.ifAttack()) {
        var _isdomain = U.A.Request.isDomain(url); //判断请求的ajax是否是跨域请求,这里是做跨域请求的方案
        //如果是在本域名下请求的处理,或者是跨域请求,没有做其他跨域方案。
        if (_isdomain == 1) {
            var _header = header || {}, //ajax对象header的设置处理
                _ajaxtype = _header.type || "POST", //设置ajax请求的类型 Get 或者是post
                _isasync = U.UF.C.isFunction(cb), //判断请求为异步函数同步
                _params = U.A.Request.toAjaxFormat(params); //把数组传参转化成ajax传参
            //创建一个全兼容的ajax对象
            var _ajaxobject = U.A.Request.createAjaxObject(url);
            //记录Ajax的创建时间,创建的请求地址,记录是否攻击及请求所花费的时间.
            U.A.Request.attack(url, params, cb, cbparams, header, _ajaxobject);

            //如果请求的类型是get,那么请求拼接链接
            if (_ajaxtype.toUpperCase() == "GET") {
                url += "?" + _params;
            }
            //打开请求,设置ajax请求方法 url 是否异步
            _ajaxobject.open(_ajaxtype, url, _isasync);

            //给ajax对象的header设置值
            U.A.Request.writeHeader(_ajaxobject, _header);

            //发送请求
            _ajaxobject.send(_params);

            //等待服务器返回的数据库的结果。
            //如果是异步,那么用异步的处理
            if (_isasync) {
                U.A.Request.asyn(_ajaxobject, cb, cbparams);
            }
            //如果是同步的处理
            else {
                return U.A.Request.getData(_ajaxobject, null);
            }
        }
        else {
            return U.A.Request.handleDomain(url, params, cb, cbparams, header, _isdomain);
        }
    }
}


/**
* 自定义传参ajax初始化区域
* 由于U.A.Request发送的请求默认传递为mode传参后的拼接参数,但有部分接口的参数名并不为mode,
* 因此定义此接口为自定义请求所服务。
* @param  {string} 访问的地址
* @param  {array} 数据库地址,数据库名,存储过程名,存储过程参数的数组
* @param  {function} 回调函数
* @param  {array} 函数传参
* @param  {object} 需要写入的header对象
* @returns {object} ajax对象 
*/
U.A.Request.Post = function (url, params, cb, cbparams, header) {
    //判断是否为攻击
    if (U.A.Request.ifAttack()) {
        var _isdomain = U.A.Request.isDomain(url); //判断请求的ajax是否是跨域请求,这里是做跨域请求的方案
        //如果是在本域名下请求的处理,或者是跨域请求,没有做其他跨域方案。
        if (_isdomain == 1) {
            var _header = header || {}, //ajax对象header的设置处理
                _ajaxtype = _header.type || "POST", //设置ajax请求的类型 Get 或者是post
                _isasync = U.UF.C.isFunction(cb), //判断请求为异步函数同步
                _params = U.A.Request.Post.toAjaxFormat(params); //把数组传参转化成ajax传参
            //创建一个全兼容的ajax对象
            var _ajaxobject = U.A.Request.createAjaxObject(url);
            //记录Ajax的创建时间,创建的请求地址,记录是否攻击及请求所花费的时间.
            U.A.Request.attack(url, params, cb, cbparams, header, _ajaxobject);
            //打开请求,设置ajax请求方法 url 是否异步
            _ajaxobject.open(_ajaxtype, url, _isasync);

            //给ajax对象的header设置值
            U.A.Request.writeHeader(_ajaxobject, _header);

            //发送请求
            _ajaxobject.send(_params);

            //等待服务器返回的数据库的结果。
            //如果是异步,那么用异步的处理
            if (_isasync) {
                U.A.Request.asyn(_ajaxobject, cb, cbparams);
            }
            //如果是同步的处理
            else {
                return U.A.Request.getData(_ajaxobject, null);
            }
        }
        else {
            return U.A.Request.handleDomain(url, params, cb, cbparams, header, _isdomain);
        }
    }
}


/**
* Post请求数据拼接
*
* @param  {array} 数组的传参
*/
U.A.Request.Post.toAjaxFormat = function (params) {
    var _key;
    var _params = '';
    for (_key in params) {
        _params += _key + '=' + encodeURIComponent(encodeURIComponent(params[_key])) + '&';
    }
    return _params.substr(0, _params.length - 1);
}

/**
* 记录Ajax的创建时间,创建的请求地址,记录是否攻击及请求所花费的时间.
*
* @param  {string} 访问的地址
* @param  {array} 数据库地址,数据库名,存储过程名,存储过程参数的数组
* @param  {function} 回调函数
* @param  {array} 函数传参
* @param  {object} 需要写入的header对象
* @returns {object} ajax对象 
*/
U.A.Request.attack = function (url, params, cb, cbparams, header, ajaxobject) {
    var _preajax = U.A.allAjaxRequest.requestObject[U.A.allAjaxRequest.requestObject.length - 1], //上一个请求
        _ajaxarray = {
            "win": window, //执行的域
            "ajax": ajaxobject, //ajax对象
            "url": url, //后台的地址
            "params": params, //后台的传参
            "cb": cb, //执行后的回调
            "cbparams": cbparams, //回调函数的传参
            "header": header, //ajax的header的处理
            "time": new Date().getTime() //ajax创建的时间
        };
    U.A.allAjaxRequest.requestNumber += 1; //这个是总的请求数
    U.A.allAjaxRequest.requestObject.push(_ajaxarray); //把ajax对象添加到全局
    //如果有上一个ajax请求的处理
    if (_preajax) {
        //如果第一次请求和第二次请求时间差为50毫秒的话,这里就默认是循环请求
        if (_ajaxarray.time - _preajax.time < 50) {
            U.A.allAjaxRequest.forrequest += 1;
        }
        else {
            U.A.allAjaxRequest.forrequest = 0;
        }
    }
    return _ajaxarray;
}

/**
* ajax把参数转成ajax的传参
* @param  {array} 数组的传参
*
*/
U.A.Request.toAjaxFormat = function (params) {
    params = params || [];
    var _userinfo,
        _params = "mode=" + U.UF.C.urlEncode(params.concat()); //参数加密处理拼接处理
    try {
        //由于1473后台对loginid 、 userid 、pageid 、systemid是直接通过url获取的,没有进行传参,那么下面就是进行1473 url的拼接
        if (parent && parent.US) { //如果有parent.US那么就是1473的项目
            _userinfo = parent.US.userInfo; //获取用户的信息
            //如果用户的信息存在那么拼接用户的信息
            if (_userinfo && _userinfo.UserId) {
                _params += "&UserId=" + _userinfo.UserId + "&LoginId=" + _userinfo.LoginId;
            }
            //设置1473项目传参的id
            _params += "&PageId=" + US.pageId + "&SystemId=" + US.systemId;
        }
    } catch (e) { }
    return _params;
}

/**
* 创建ajax请求对象 XMLHttpRequest或者 ActiveXObject对象
* @param  {string} ajaxurl的地址
*
*/
U.A.Request.createAjaxObject = function (url) {
    //ie8,ie9跨域兼容
    var _locationurl = window.location ? (window.location.protocol + "//" + window.location.host) : ""; //url的链接
    if (url.indexOf(_locationurl) == -1 && window.XDomainRequest) {//在ie8、9中允许用ajax跨域访问 但是不支持XMLHttpRequest跨域而是一个新的函数XDomainRequest,后面废除了。
        return new window.XDomainRequest();
    }
    //这里创建Ajax对象
    try { return new XMLHttpRequest(); } catch (e) { }
    //ie6以下的浏览器处理,包含一些可解析脚本插件处理,//ie6系列等直接脚本的浏览器支持的插件
    //Internet Explorer
    try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch (e) { }
    try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { }
    try { return new ActiveXObject('MSXML3.XMLHTTP'); } catch (e) { }
    try { return new ActiveXObject('MSXML.XMLHTTP'); } catch (e) { }
    try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { }
    try { return new ActiveXObject('MSXML2.ServerXMLHTTP'); } catch (e) { }
    //alert("你的浏览器不支持xmlhttp对象,所以一些功能无法使用,建议使用高版本的浏览器!!");
}

/**
* 给ajax对象写入head
* @param  {object} ajax对象
* @param  {object} 需要写入的header
*/
U.A.Request.writeHeader = function (ajax, header) {
    header["CONTENT-TYPE"] = header["CONTENT-TYPE"] || "application/x-www-form-urlencoded;charset=UTF-8"; //请求写入数据的格式,必须传值,否则后台获取值会报错
    //header["Connection"] = "keep-alive";
    header["timeout"] = 10000;
    //循环给ajax对象设置header
    for (var i in header) {
        try {
            //ajax属性里面有方法的设置
            if (i in ajax) {
                ajax[i] = header[i];
            }
            //不是ajax属性的设置header
            else {
                ajax.setRequestHeader(i, header[i]);
            }
        }
        catch (e) { }
    }
    // 指定服务器返回数据的MIME类型 firfox设置兼容,不设置frifox浏览器后台无法获取值
    if (ajax.overrideMimeType) {
        if (header["responseType"] == "blob") {
            ajax.overrideMimeType("text/plain; charset=x-user-defined");
        } else {
            ajax.overrideMimeType("text/html");
        }
    }
}

/**
* ajax异步处理函数
* @param  {object} ajax对象
* @param  {function} 回调函数
* @param  {array} 回调参数
*/
U.A.Request.asyn = function (ajaxobject, cb, params) {
    //判断是否需要loading处理,如果需要loading处理,那么在第一个元素中添加loading
    if (params && params[0] && U.UF.C.isElement(params[0])) {
        U.UF.DL.loading(params[0]);
    }

    //正常的ajax的回调处理
    if (ajaxobject.onreadystatechange !== undefined) {
        //设置ajax回调处理
        ajaxobject.onreadystatechange = function () {
            if (ajaxobject.readyState == 4) { //已经加载成功
                //判断是否有loading处理,如果有则移除
                if (params && params[0] && U.UF.C.isElement(params[0])) {
                    U.UF.DL.uploading(params[0]);
                }
                var _data = U.A.Request.getData(ajaxobject, params); //获取ajax的返回值
                cb.call(cb, _data); //回调处理
            }
        }
        //ajax超时处理
        ajaxobject.ontimeout = function () {
            return false;
        }
    }
    //ajax支持onload事件的处理,由于ie8、ie9跨域的XDomainRequest对象只支持onload
    else {
        ajaxobject.ontimeout = function () { }
        //错误处理,下面用onreadystatechange已经把这个功能包含进去
        ajaxobject.onerror = function () {
            ajaxobject.status = 500; //由于这个请求对象不会自动设置500错误,但是为了统一判断,这里设置默认的错误500
            cb.call(cb, { //返回的ajax对象
                httpRequest: ajaxobject,  //xmlrequest对象
                status: {  //服务器响应的状态 200成功,其他的都是失败
                    "status": ajaxobject.status,
                    "statusText": ajaxobject.statusText
                },
                value: null, //服务器返回的值
                context: params //回调函数的参数
            }); //回调处理
        };
        //设置ajax回调处理
        ajaxobject.onload = function () {
            //判断是否有loading处理,如果有则移除
            if (params && params[0] && U.UF.C.isElement(params[0])) {
                U.UF.DL.uploading(params[0]);
            }
            var _data = U.A.Request.getData(ajaxobject, params); //获取ajax的返回值
            cb.call(cb, _data); //回调处理
        }
    }
}

/**
* 获取ajax的值
* @param  {object} ajax对象
* @param  {function} 回调函数
*/
U.A.Request.getData = function (ajaxobject, cbparams) {
    var _data, //服务器返回的值
        _returnobj = { //返回的ajax对象
            httpRequest: ajaxobject,  //xmlrequest对象
            status: 200,  //服务器响应的状态 200成功,其他的都是失败
            value: null, //服务器返回的值
            context: cbparams //回调函数的参数
        };

    //返回值的正确处理
    if (ajaxobject.status == 200 || ajaxobject.status == null) {
        //服务器返回的是xml对象的处理
        if (ajaxobject.responseXML && ajaxobject.responseXML.xml) {
            _data = ajaxobject.responseXML.xml; //xml的值
        }
        //服务器返回的是string的处理
        else {
            _data = U.UF.C.toJson(ajaxobject.responseText); //获取转化成ajax的对象
        }
        _returnobj.value = _data; //设置服务器返回的值
    }
    //错误处理
    else {
        //ajax错误处理
        _returnobj.status = {
            "status": ajaxobject.status,
            "statusText": ajaxobject.statusText
        };
    }

    //关闭连接,释放资源
    if (ajaxobject.abort) {
        ajaxobject.abort();
    }

    //请求得到值的整个过程的时间差处理
    U.A.Request.timeSpan(ajaxobject, _returnobj);
    //返回得到的值
    return _returnobj;
}


/**
* 判断ajax是否跨域处理
* @param  {string} 请求的地址
*返回值:1相同域名不跨域*2为跨子域,3为完全跨域
*/
U.A.Request.isDomain = function (url) {
    var _frame,
        _a = $$("a", { "href": url }) //创建一个a标签能得到 url请求的地址的域
        ;
    //如果是直接浏览器打开文件的方式 如e:/a.html这样打开的则没有window.location
    if (window.location) {
        //相同域名也不跨子域的情况
        if (url.indexOf(window.location.host) == 0) {
            return 1;
        }
        //相同域名也跨子域的情况
        else if (window.location.host.split(".").slice(-2).join(".") == _a.hostname.split(".").slice(-2).join(".")) {
            _frame = window.frames; //所有加载的域,对1473域下所有iframe进行循环,目的是找到可跨域的iframe。
            //循环所有可跨域的iframe进行处理
            for (i = 0; i < _frame.length; i++) {
                try {
                    if (_frame[i].location.host && _a.host.indexOf(_frame[i].location.host) == 0) { //找到指定的跨域
                        return 2; //跨域获取
                    }
                }
                catch (e) {
                }
            }
        }
    }
    //完全跨域的情况,这里的要求是必须创建iframe id和name为U_Domain的
    // if ($("#U_Domain")[0]) {
    //    return 3;
    //}
    return 1; //如果开发者跨域了,也没有用跨域解决方案,也默认给他调用ajax的方法,因为在高版本的浏览器中已经支持xmlrequest跨域了
}

/**
* ajax异步处理的方式
*
* @param  {string} 访问的地址
* @param  {array} 数据库地址,数据库名,存储过程名,存储过程参数的数组
* @param  {function} 回调函数
* @param  {array} 函数传参
* @param  {object} 需要写入的header对象
* @param  {object} 跨域的方式 2 相同域名也跨子域的情况 3 完全跨域的情况
*/
U.A.Request.handleDomain = function (url, params, cb, arg, header, isdomain) {
    var _newsinfo,
        _a = $$("a", { "href": url }), //创建一个a标签能得到 url请求的地址的域
        _frame;
    //相同域名也跨子域的情况
    if (isdomain == 2) {
        _frame = window.frames; //所有加载的域,对1473域下所有iframe进行循环,目的是找到可跨域的iframe。
        //循环所有可跨域的iframe进行处理
        for (i = 0; i < _frame.length; i++) {
            try {
                if (_a.hostname.indexOf(_frame[i].location.hostname) == 0) { //找到指定的跨域
                    return _frame[i].U.A.Request(url, params, cb ? function (data) { setTimeout(function () { cb.call(window, data) }); } : null, arg, header); //跨域获取
                }
            }
            catch (e) {
            }
        }
    }
    //完全跨域的情况,这里的要求是必须创建iframe id和name为U_Domain的
    else if (isdomain == 3) {
        //判断是否需要loading处理,如果需要loading处理,那么在第一个元素中添加loading
        if (params && U.UF.C.isElement(params[0])) {
            U.UF.DL.uploading(params[0]);
        }
        //跨域执行ajax处理 fun, issender, iframeid, url, id
        _newsinfo = new U.UF.EV.message(
        function (data, id, cookie) { //接受到跨域的ajax的回调处理 data[0]是执行ajax后台返回的值 data[1]是执行的cookie处理
            //后台设置了cookie 前台同时响应
            if (cookie == "") { //删除cookie的值
                U.UF.Cookie.del(cookie);
            }
            //如果在和后台交互的过程设置了cookie,那么这里需要设置
            else {
                U.UF.Cookie.set(cookie);
            }
            var _data = { //返回的ajax对象
                httpRequest: null,  //xmlrequest对象
                status: 200,  //服务器响应的状态 200成功,其他的都是失败
                value: data, //服务器返回的值
                context: arg //回调函数的参数
            };
            cb.call(cb, _data); //回调处理
        }, true, "domain", "U_Domain");
        //跨域传参
        _newsinfo.post([url, params], "domain");
    }
    return false; //如果开发者跨域了,也没有用跨域解决方案,也默认给他调用ajax的方法,因为在高版本的浏览器中已经支持xmlrequest跨域了
}

/**
* 判断用户是否连续发送ajax请求到后台,如果是我们视为攻击,返回false,否则是true
*/
U.A.Request.ifAttack = function () {
    var _isfor = U.A.allAjaxRequest.forrequest < 50; //获取是否循环进行ajax处理,如果超过50次我们认为是攻击ajax
    //如果为攻击ajax,那么就等待清楚攻击
    if (!_isfor) {
        setTimeout(function () { U.A.allAjaxRequest.forrequest = 0; })
    }
    return _isfor;
}

/**
* 请求时间差处理
* @param  {object} ajax对象
* @param  {object} 服务器返回值
*/
U.A.Request.timeSpan = function (ajaxobject, request) {
    var i,
        _timespan,
        _arr = U.A.allAjaxRequest.requestObject; //所有请求的ajax对象
    //循环数组的对象
    for (i = 0; i < _arr.length; i++) {
        try {
            //整个ajax的对象
            if (_arr[i].ajax == ajaxobject) {
                _timespan = new Date().getTime() - _arr[i].time; //请求时间差
                U.UF.C.console({ "timespan": _timespan, "request": request }); //控制台输出请求的时间差和值
            }
        } catch (e) { }
    }
}

//#endregion
;
///<jscompress sourcefile="ClientInfo.js" />
Namespace.register("U.UF.CI");

//#region 客户端信息

//浏览器信息
U.UF.CI.userAgent = navigator.userAgent.toLowerCase();

/*
* 获取去新浪获取地址信息
*
* @param  {function} 获取客户端信息回调
*/

//朱艳萍老师建议:用释义的方式更加利于学生理解,也更加便于此系统的普及及应用,建议采纳。
//Usestudio.UnionForm.getUserLocation
U.UF.CI.getUserLocation = function (fun) {
    //如果用户客户端信息已经加载成功
    if (US.city["country"]) {
        fun(); //回调函数
    }
    else {
        //如果没有加载成功,那么通过加载新浪的api去加载
        //新浪的用不了了,现在使用的是搜狐的api
        U.UF.DL.asynLoadJs({ "src": "http://pv.sohu.com/cityjson?ie=utf-8" },
                            function () {
                                var _city = U.UF.CI.asyngetUserLocation(); //得到城市地址
                                fun(_city); //打印城市信息
                            });
    }
}

/*
* 获取客户端ip异步
returnCitySN
参数描述
-------cname 当前城市
-------cid 当前城市id
-------cip 当前城市ip
*
* 
*/
U.UF.CI.asyngetUserLocation = function () {
    try {
        var _script = U.UF.DL.asynLoadJs({ "src": "http://pv.sohu.com/cityjson?ie=utf-8" }, function () { });
        //引入搜狐的script模块
        var i,
               _locationinfo = returnCitySN, //搜狐返回的值
        //用户地址信息数组
               _locationarr = [
                                "country",
                                "province",
                                "city",
                                "district",
                                "isp",
                                "type"
                           ];
        _locationinfo.userAllLocation = ""; //用户地址拼接的处理
        //循环需要拼接的数组处理
        for (i = 0; i < _locationarr.length; i++) {
            _locationarr["userAllLocation"] += _locationarr[_locationinfo[i]];
            if (i != _locationarr.length - 1) {
                _locationarr["userAllLocation"] += ",";
            }
        }
        //把从第三方获取的值放在US.city变量中
        //alert("当前城市的ip值为" + _locationinfo.cip);
        US.city = _locationinfo;
        cb(_locationinfo); //回调使用
    }
    catch (e) { return; }
}


/*
* 获取浏览器类型
*
* @return  {object} 浏览器类型{ "browser": "", "ver": "" }
---------browser 浏览器类型 如 ie  chrome firefox safir
---------ver 浏览器版本 如果ie的 7.0 8.0 和chrome 33 34
*/
U.UF.CI.getBrowser = function () {
    var _browserobj = { "browser": "", "ver": "" }, //返回的浏览器对象
        _bri = U.UF.CI.userAgent, //浏览器信息
        _bro = U.UF.S.browser, //区分浏览器的正则
        _browserarr = _bri.match(_bro)//利用正则反选择的方式获取数组
    ;
    _browserobj.browser = _browserarr[1]; //设置浏览器的名字如  msie  chrome firefox safir
    _browserobj.ver = _browserarr[2]; //设置浏览器版本号 ie的 7.0 8.0 和chrome 33 34
    return _browserobj;
}

/*
* 获取用户电脑系统
*
* @return  {string} 成功回调
*/
U.UF.CI.getSystem = function () {
    //非window系列的说明
    var _ant = {
        "Apple series": "Mac68K,MacPPC,Macintosh",
        "Unix series": "X11",
        "Mac OS X 10_7": "OSX 10.7",
        "Mac OS X 10.8": "OSX 10.8",
        "Mac OS X 10_8": "OSX 10.8",
        "Linux": "Linux"
    };

    var _win = {
        "Windows NT 5.1": "WinXP", //windows 系列 系统信息
        "Windows NT 6.1": "Win7",
        "Windows NT 6.0": "Windows Server 2008",
        "Windows NT 6.2": "Win8",
        "Windows NT 5.1": "winxp",
        "Windows NT 5.2": "Windows Server 2003",
        "Windows NT 5.0": "Win2000",
        "Win 9x 4.90": "WinME",
        "Windows NT 10.0": "Win10"
    };

    var _str = navigator.userAgent; //获取用户信息
    var _left = _str.indexOf('(');
    var _right = _str.indexOf(';');

    //截取系统信息
    var _result = _str.substring(_left + 1, _right);
    return _win[_result] || _ant[_result]; //返回系统名称
}

/*
* 判断用户支持html5 还是flash
*
* @return  {string} 判断是否支持flash或者html5
-----------HTML5 支持html5
-----------Flash 支持flash
*/
U.UF.CI.isSupportFlash = function () {
    if (typeof (Worker) !== "undefined")   //利用worker属性判断是否支持html5
    {
        return 'HTML5';
    }
    else if (navigator.plugins["Shockwave Flash"]) {//利用navigator.plugins["Shockwave Flash"]属性判断是否支持flash
        return "Flash";
    }
    else {
        return false;
    }
}



/*
* 获取客户端为电脑端还是手机端
* @return  {boolean} 
-----------true 电脑端
-----------false 手机端
*/
U.UF.CI.getUserPort = function () {
    var _userAgentInfo = navigator.userAgent, //浏览器信息
        _agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"], //常用的手机系统版本
        _flag = true,    //建立标志
        i; //用于循环
    //循环判断浏览器信息中是否有手机端是否有
    for (i = 0; i < _agents.length; i++) {
        if (_userAgentInfo.indexOf(_agents[i]) > 0) {
            _flag = false;    //如果是手机版本返回false
            break;
        }
    }
    return _flag; //如果不是手机端返回true
}

/*
* 获取分辨率
* @return  {array} [deviceXDPI, deviceYDPI];
*/
U.UF.CI.getDPI = function () {
    var arrDPI = new Array();
    if (window.screen.deviceXDPI != undefined) {
        arrDPI[0] = window.screen.deviceXDPI;
        arrDPI[1] = window.screen.deviceYDPI;
    }
    else {
        var tmpNode = document.createElement("DIV");
        tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
        document.body.appendChild(tmpNode);
        arrDPI[0] = parseInt(tmpNode.offsetWidth);
        arrDPI[1] = parseInt(tmpNode.offsetHeight);
        tmpNode.parentNode.removeChild(tmpNode);
    }
    return arrDPI;
}
//#endregion
;
///<jscompress sourcefile="Common.js" />
/*
此函数区域用于常用的通用函数 如位置 大小 计时器等
*/
Namespace.register("U.UF.C");
//#region 通用函数区域

/**
* 浏览器全屏
*
*/
U.UF.C.fullScreen = function () {
    var _funcname = U.UF.C.getFullSreeenName("requestFullScreen"); //全屏函数名
    if (_funcname != null) {
        document[_funcname] ? document[_funcname]() : document.documentElement[_funcname]();   //执行全屏函数
    }
}

/**
* 退出浏览器全屏
*
*/
U.UF.C.cancelfullScreen = function () {
    var _funcname = U.UF.C.getFullSreeenName("cancelFullScreen") || U.UF.C.getFullSreeenName("exitFullScreen"); //全屏函数名
    if (_funcname != null) {
        document[_funcname] ? document[_funcname]() : document.documentElement[_funcname]();   //执行退出全屏函数
    }
}

/**
* 根据函数名获取浏览器兼容名字
** @return  {string} 全屏功能的函数名 
*/
U.UF.C.getFullSreeenName = function (funcname) {
    var i, _functionname;
    //各个浏览器的全屏函数名称是不一样的,用数组把各个全屏函数包装起来。
    //注:各个浏览器全屏函数名如数组: _full = ["requestFullscreen", "mozRequestFullScreen", "webkitRequestFullscreen", "msRequestFullscreen", "oRequestFullscreen"];
    //各个浏览器还有不同的取消全屏,退出全屏功能"cancelFullScreen","exitFullScreenU.UF.C.getBriefText" 
    var _full = ["", "webkit", "moz", "ms", "o"]; //所有浏览器的兼容字符串集
    for (i = 0; i < _full.length; i++) {
        if (_full[i]) {
            _functionname = _full[i] + funcname.capitalizeFirstLetter();
        }
        else {
            _functionname = funcname;
        }
        //判断拼接的浏览器兼容函数名在文档中是否存在。存在则返回函数,不存在返回null。
        if (_functionname in document.documentElement || _functionname in document) {
            return _functionname;
        }
    }
    return null;
}

/**
* 对象转化成数组
*
* @param  {object} 需要转换成数组的对象
* @return  {string} 指定事件是否在捕获或冒泡阶段执行
*/
U.UF.C.toArray = function (obj) {
    try {
        return Array.prototype.slice.call(obj);
    }
    catch (e) {
        var i = 0,
            _arr = []; //循环创建
        for (; obj[i]; i++) {
            _arr.push(obj[i]);
        }
        return _arr;
    }
}

/**
* 统一处理函数,解决闭包添加事件的问题
* 使用apply,把事件与属性添加到对象上,而不是添加到window顶级对象。使用apply而不是call,是因为apply第二个参数可以传递参数数组,代码更少。
* 调用方法 U.UF.C.apply(this,'执行函数的事件')  例如 U.UF.C.apply(this,'this.style.display="none"');
*
* @param  {object} 将要绑定事件与属性的对象,如没有,可以传递null或者this,此处还需要优化,很多地方都会调用此函数,会导致速度降低。
* @param  {object} 函数与参数组成的数组。

案例:U.FC.C.apply(this,function(){});  //this用dialog做案例.
案例: U.FC.C.apply(element,function(){});
案例:U.FC.C.apply(element,function(){
//执行其他函数
});
*/
U.UF.C.apply = function (scope, fun) {
    //返回一个在指定域下执行的函数
    return function () {
        fun.call(scope || this);
    }
}


/*
解决给元素循环赋予事件及闭包的问题函数名称为:U.FC.C.closure
案例:U.FC.C.apply(element,function(){
//执行其他函数
});

//不用闭包的解决方法。
//当给元素循环赋予事件时,为了解决事件始终聚焦在最后一个元素的问题,可以采用闭包的写法,但毕竟复杂。
for(var i = 0;i<100;i++){
//使用闭包的写法
div[i].onclick=clickfun(i,div[i]);
}
function clickfun(j,el){
return function(){
el.style.backgroudcolor = '#000';
}  
}


//当给元素循环赋予事件时,为了解决事件始终聚焦在最后一个元素的问题,可以采用闭包的写法,但毕竟复杂。
for(var i = 0;i<100;i++){
//使用闭包的写法
div[i].onclick=function(j,el){
return function(){
div[j].style.backgroudcolor = '#000';
}  
}(i,div[i]);
}


//为了解决此问题,优化方案如下:
for(var i = 0;i<100;i++){
div[i].onclick =  U.FC.C.apply(i,div[i],clickfun);
}
function clickfun(j,el){
el.style.backgroudcolor = '#000';
}
*/
U.UF.C.closure = function (fun, parms) {
    //创建一个函数返回
    return function () {
        return fun.apply(this, parms)
    }
}


/**
* 获取 rgb颜色值
*
* @param  {array} 进行操作的对象 
* @return  {string} 确定循环范围 
*/
U.UF.C.getColorByRGB = function (style) {
    var i, //循环初始化
        _color = "#", //rgb颜色前缀
        _grbarr = style.match(U.UF.S.rgb); //判断颜色是不是rgb值
    //如果是rgb那么转化成#nnnnnn的值
    if (_grbarr) {
        for (i = 1; i < _grbarr.length; i++) {
            _color += ("0" + _grbarr[i].toInt().toString(16)).slice(-2); //转换的方式
        }
        return _color;
    }
    return style;
}

/**
* 获取url参数
*
* @param  {string}  QueryString key
* @param  {string}  QueryString 默认为window.document.location.search ,可以自己选择字符串进行拆分
* @return  {string}  获取key对应的值
*/
U.UF.C.queryString = function (key, search) {
    var _search = (search || window.document.location.search).substr(1);
    var i, j,
        _return = "",
        _valuearr, //网页传参 key和value组成的数组
        _arr = _search.split("&"); //生成传参数组
    for (i = 0; i < _arr.length; i++) { //循环传参数组获取值
        _valuearr = _arr[i].split("="); //把网页传参拆分
        if (_valuearr[0].toUpperCase() == key.toUpperCase()) { //判断key是否相等
            for (j = 1; j < _valuearr.length; j++) { //返回值
                _return += _valuearr[j] + (j == _valuearr.length - 1 ? "" : "="); //拼接返回值
            }
            break;
        }
    }
    return _return;
}

/**
* 获取地址hash
*
*/
U.UF.C.getUrlHash = function () {
    var _hash = document.location.hash; //地址传参
    return _hash.split("/");
}

/**
* 判断Url是否合法
*
* @param  {string} url值
* @return  {boolean} 是否盒饭的url
*/
U.UF.C.isUrl = function (str) {
    //获取参数
    var _str = str;
    //正则表达式字符串
    var _String = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
    //new 一个正则表达式
    var _objExp = new RegExp(_String);
    //正则表达式判断是否有http等合法标识
    if (_objExp.test(str) == true) {
        return true;
    } else {
        return false;
    }
}


/**
* 设置iframe同一个域,创建空iframe,在iframe中设置域名,等待iframe加载完回调。
*
* @param  {element} iframe
* @param  {string} 写入iframe的值
* @param  {function} 成功的回调函数
* @return  {element} 返回iframe
*/
U.UF.C.iframeSameDomain = function (iframe, htmlstr, cb) {
    //iframe设置onload事件的回调
    U.UF.DL.iframeLoad(iframe, function () {
        if (htmlstr) {
            iframe.contentWindow.document.body.innerHTML = htmlstr;
        }
        if (cb) {
            cb();
        }
    });
    //设置iframe的链接,这里设置的是空链接(空连接分为两种,一种是带domain有域名的,这种创建需要创建一个带域名的,第二种是没有域名的比如localhost或者f://1.html打开的页面)
    iframe.src = document.domain ? "javascript:void((function(){document.open();document.domain='" + document.domain + "';document.close()})())" : "about:blank"; //添加链接 "about:blank";
    return iframe;
}

/**
* url中文加密,用于ajax
*
* @param  {array} 需要加密的字符串数组 这个为url加密
* @return  {array} 返回加密成功的url数组
*/
U.UF.C.urlEncode = function (arr) {
    var i; //循环初始化
    for (i = 0; i < arr.length; i++) {
        arr[i] = encodeURIComponent(encodeURIComponent(arr[i]));
    }
    return arr.join(",");
}

/**
* 文字复制
*
*/
U.UF.C.copy = function () {
    if (window.clipboardData) { //ie
        window.clipboardData.setData("text", copystr);
    }
    else if (event && event.clipboardData) {//html5兼容
        event.clipboardData.setData("text/HTML", copystr);
    }
    else if (event && event.originalEvent && event.originalEvent.clipboardData) { //firfox兼容
        event.originalEvent.clipboardData("Text", copystr);
    }
    else if (document.execCommand) { //基本全兼容除了手机端的safari
        document.execCommand("copy");
        return document.execCommand("copy");
    }
    else {
        U.alert("请手动选择复制");
    }
}

/**
* 文字粘贴剪贴板
*
*/
U.UF.C.pasteText = function () {
    if (window.clipboardData) { //ie
        return window.clipboardData.getData("text");
    }
    else if (event.clipboardData) { //html5
        var _str = event.clipboardData.getData("text/HTML"); //获取带html的文本
        if (!_str) { //如果文本不存在,则通过纯文本获取
            _str = event.clipboardData.getData("text/plain").replaceAngleBrackets();
        }
        return _str;
    }
    else if (event && event.originalEvent && event.originalEvent.clipboardData) { //firfox兼容
        return event.originalEvent.clipboardData("Text")
    }
    else if (document.execCommand) { //基本全兼容除了手机端的safari
        if (document.execCommand("paste") == true) {
            document.execCommand("paste");
            return document.execCommand("paste");
        } else {
            U.alert && U.alert("无法粘贴");
            return false;
        }
    }
    else {
        U.alert && U.alert("无法粘贴");
    }
}

/*
**作用:对元素在点击右键或者左键的时候,制定的菜单元素定位到鼠标点击的附近。
**@param {element} el     需要定位的右键菜单元素
*/
U.UF.C.rightClickMenuLocation = function (el) {
    //获取鼠标当前位置
    var _e = event || window.event, //获取事件源
        _elementposition = U.UF.EL.getElementPosition(el), //获取元素的位置
	    _getmousex = _e.clientX - _elementposition[1], //获取鼠标的X坐标
	    _getmousey = _e.clientY - _elementposition[0], //获取鼠标的Y坐标
        _eloffsetp = U.selectEl(el).Parent(), //获取需要定位的右键菜单元素的offsetParent
	    _ellocationw = el.offsetWidth, //获取定位的右键菜单元素的offsetWidth属性
	    _ellocationh = el.offsetHeight, //获取定位的右键菜单元素的offsetHeight属性
	    _eloffsetpw = _eloffsetp.offsetWidth, //获取元素offsetParent的offsetWidth属性
	    _eloffsetph = _eloffsetp.offsetHeight; //获取元素offsetparent的offsetHeight属性
    //判断top的最大范围
    if ((_ellocationw + _getmousex) > _eloffsetpw) {//如果定位元素的offsetWidth和鼠标X坐标的和大于元素offsetParent的offsetWidth
        _getmousex = _getmousex; // -_ellocationw; //则鼠标的X坐标为原先的鼠标X坐标减去定位元素的offsetWidth
    }
    else {
        _getmousex = _getmousex; //否则,鼠标的X坐标还是为原先的鼠标X坐标
    }
    //判断left的最大范围
    if ((_ellocationh + _getmousey) > _eloffsetph) {//如果定位元素的offsetHeight和鼠标X坐标的和大于元素offsetParent的offsetHeight
        _getmousey = _getmousey; // - _ellocationh; //则鼠标的Y坐标为原先的鼠标Y坐标减去定位元素的offsetHeight
    }
    else {
        _getmousey = _getmousey; //否则,鼠标的X坐标还是为原先的鼠标Y坐标
    }
    U.selectEl(el)[0].style.top = _getmousey + "px"; //添加右键菜单的top坐标
    U.selectEl(el)[0].style.left = _getmousex + "px"; //添加右键菜单的left坐标
}


/**
* 序列化json为字符串
*
* @param  {object 、 array} 需要序列化对象
* @returns {string} json为字符串 
注释:在写api时需要获取数据库返回值并转化为可识别字符串时经常用到。可精简名字,写成好的api
*/
U.UF.C.jsonToStr = function (o) {
    var r = [];
    if (typeof o == "string") {
        return "\"" + o.replace(/([\'\"\\])/g, "\\$1").replace(/(\n)/g, "\\n").replace(/(\r)/g, "\\r").replace(/(\t)/g, "\\t") + "\"";
    }
    if (typeof o == "object") {
        if (!o.sort) {
            for (var i in o) {
                r.push(i + ":" + U.UF.C.jsonToStr(o[i]));
            }
            if (!!document.all && !/^\n?function\s*toString\(\)\s*\{\n?\s*\[native code\]\n?\s*\}\n?\s*$/.test(o.toString)) {
                r.push("toString:" + o.toString.toString());
            }
            r = "{" + r.join() + "}";
        }
        else {
            for (var i = 0; i < o.length; i++) {
                r.push(U.UF.C.jsonToStr(o[i]));
            }
            r = "[" + r.join() + "]";
        }
        return r;
    }
    if (o == null) {
        return "null";
    }
    else { return o.toString(); }
}

/**
* 返回制定的对象类型名
*
* @param  {object} 需要判断的对象
* @return  {string} 返回object转化后的的
*/
U.UF.C.objectToString = function (obj) {
    return Object.prototype.toString.call(obj);
}

/**
* 监听用户是否断网
*
* @param  {function} 需要判断的对象
* @return  {boolean} 是否联网
*/
//U.UF.C.monitorInternet = function (fun) {
//    window.addEventListener("online", fun);
//    window.addEventListener("offline", fun);
//}

/**
* 错误函数控制台处理,,,解决ie的问题
*
* @param  {string} 输入控制台的类型 默认log
* @return  {object} 输出控制台的值
*/
U.UF.C.console = function (err) {
    try {
        //        console.log(err);
        return;
    }
    catch (e) { }
}

/**
* html加载,存储一篇文章,javascritp可以放在任何地方,当把文章追加到div等元素中时,由于没有刷新,导致javascript不能执行。需要把javascript重新移动到head头部才会加载。
*
* @param  {element} 任何html元素 
* @param  {string} 文章内容 
@return  返回文章内容
*/
U.UF.C.loadJs = function (el, htmlstr) {
    if (htmlstr != null) {
        el.innerHTML = htmlstr;
    }
    var i, //循环初始化
        _head = U.selectEl("head"),
        _scripts = U.selectEl("script", el); //获取script标签
    //循环把js的标签写入
    for (i = 0; i < _scripts.length; i++) {
        //uform.js就不重新加载了,因为可以调用到该函数说明uform.js还能正常使用
        if (_scripts[i].src) {
            U.UF.DL.asynLoadJs({ "src": _scripts[i].src });
        } else {
            //追加元素
            $$("script", { "type": _scripts[i].type || 'text/javascript' }, _head[0]).text = _scripts[i].text;
        }
    }
    return htmlstr;
}


/**
* 
*
* @param  {element} 任何html元素 
* @param  {string} 文章内容 
*/
U.UF.C.toJson = function (str) {
    var i,
        _json = str; //转化成字符串
    //如果传进来的值是字符串那么就转化成json
    if (U.UF.C.isString(str)) {
        _json = str.parseJSON();
    }
    if (Array.isArray(_json)) {
        //如果转成的json是arrayjson那么循环,看看有没有需要转化成json值得
        for (i = 0; i < _json.length; i++) {
            if (U.UF.C.isString(_json[i])) { //如果下标还是字符串的话,需要继续转化
                _json[i] = _json[i].parseJSON(); //字符串转化成json处理
            }
            else if (Array.isArray(_json[i])) { //如果是数组的处理
                U.UF.C.toJson(_json[i]);
            }
        }
    }
    //返回数据
    return _json;
}


/**
* 获取文字简写
*
* @param  {element、 string} 传入的对象或者文字
* @param  {number} 截图的长度
* @param  {string} 后缀的添加
*/
U.UF.C.getBriefText = function (el, length, str) {
    if (el.length > length) {
        var _el = U.UF.C.isString(el) ? $$("div", { "innerHTML": el }) : el; //截取的对象
        var _length = length || 200; //截取的长度
        var _str = str || ""; //省略号
        var _biretext = _el.innerText.substring(0, _length) + (_el.innerText._length > 200 ? _str : "") + str; //得到缩写加省略号
        return _biretext;
    }
    return el;
}

/**
* 禁止元素选择文字
*
*/
U.UF.C.shieldedSelect = function () {
    var _editel = U.UF.EL.getAncestorEditElement(event.srcElement); //获取一个可编辑元素
    //如果是可编辑元素,那么不禁止元素可选择
    if (_editel && (_editel.nodeType == 3 || _editel.contentEditable == "true" ||
                    "textarea,input".indexOf(_editel.tagName.toLocaleLowerCase()))) {
        return true;
    }
    U.UF.EV.stopBubble(); //取消冒泡
    U.UF.EV.stopDefault(); //取消浏览器默认行为
    return false; //禁止右键菜单
}

/**
* 禁止页面点击backspace键的时候整个网页回退
*
*/
U.UF.C.shieldedBackspace = function () {
    if (event.keyCode == 8) { //不允许按下后台键
        //如果按下回车键的区域不在可编辑区内,那么可能会发生网页回退,这里判断如果非可编辑区域,直接阻止出发backspace
        if (U.UF.EL.getAncestorEditElement((event.srcElement)) == document.body && !document.body.isContentEditable) {
            U.UF.EV.stopDefault();
        }
    }
}

/**
* 判断是否为对象
*
* @param   {object} 判断对象是否为object对象
* @return  {boolean} 是否为FormData
*/
U.UF.C.isObject = function (obj) {
    return (typeof obj == "object" && obj !== null);
}

/**
* 判断是否为数字
*
* @param  {array} 判断数组是否有值
* @return  {boolean} 是否为number
*/
U.UF.C.isNumber = function (obj) {
    return typeof obj == "number";
}

/**
* 判断是否为字符串
*
* @param  {string} 判断的字符串
* @return  {boolean} 是否为字符串
*/
U.UF.C.isString = function (str) {
    return typeof str == "string"
}

/**
* 判断是否为函数类型
*
* @param  {function} 函数值
* @return  {boolean} 函数对象值
*/
U.UF.C.isFunction = function (fun) {
    var _isfun = typeof fun == "function"; //直接通过类型判断是否为函数
    var _isobjfun = U.UF.C.objectToString(fun) == "[object Function]";   //通过对象名判断是否为函数
    return _isfun || _isobjfun;  //只要二者符合其一即为函数  且返回判断结果
}

/**
* 判断是否为元素,用于在窗体中判断用户传入的是字符串还是元素
*
* @param  {element} 元素
* @return  {boolean} 返回是否为元素 同时不为文本元素
*/
U.UF.C.isElement = function (el) {
    return el != null && el.nodeType != null;
}

/**   
* 该函数存在问题 但由于多处使用暂不删除
* 函数的作用是给已有的集合添加新的属性。
*说明:此函数代替U.Json中的Add方法,以避免调试难调,速度降低的问题
* @param  {object} U.UF.CD的自定义变量或者Array,Object等系统变量
* @param  {object} 属性的集合,形如:{ "domain": "1473.cn", "SystemId": 0}
*/
U.UF.C.AddObj = function (obj1, obj2) {
    for (var i in obj2) {
        if (obj2.hasOwnProperty(i)) {
            obj1[i] = obj2[i];
        }
    }
    return obj2;
}

//计算文件大小,小于1024用B,大于1024用KB,大于1024*1024用MB,大于1024*1024*1024用GB
//参数一:  整形,文件大小.
//返回值:字符串,小于1024用B,大于1024用KB,大于1024*1024用MB,大于1024*1024*1024用GB
U.UF.C.computeFileSize = function (size) {
    var _s; //返回的文件大小
    if (size > 1024) {
        if (size / 1024 > 1024) {
            if (size / (1024 * 1024) > 1024) {
                _s = (size / (1024 * 1024 * 1024)).toFixed(2) + 'GB'; //返回GB
            }
            else {
                _s = (size / (1024 * 1024)).toFixed(2) + 'MB'; //返回MB
            }
        }
        else {
            _s = (size / 1024).toFixed(2) + 'KB'; //返回KB
        }
    }
    else {
        _s = size.toFixed(2) + 'B'; //返回B
    }
    return _s;
}

/*移除危险标签*/
U.UF.C.filterTag = function () {

}

;
///<jscompress sourcefile="Compatible.js" />
//#region 浏览器兼容使用
/*
设置兼容性的写法 ie里面有innerText,outerHTML,而HTML5没有这些属性,为了使得TML5兼容ie特性,写了如下兼容js,HTML5也在逐步形成上诉函数。
*/
Namespace.register("U.UF.CP"); //C是compatible兼容的简写


//通过修改浏览器内置属性 设置兼容,添加兼容,此兼容模块兼容ie6以上,firefox,safiry,chrome
/**
* 滚轮事件兼容
*
* @param  {function} fun 滚动时触发的函数
*/
U.UF.CP.wheel = function (fun) {//onwheel支持所有html5浏览器  onmousewheel 支持所有非firefox的浏览器   DOMMouseScroll支持firefox浏览器
    this.onwheel = fun; //onwheel 事件在鼠标滚轮在元素上下滚动时触发
}

/**
* 滚轮事件兼容
*/
U.UF.CP.wheelGet = function () {
    return this.onwheel; //onwheel 事件在鼠标滚轮在元素上下滚动时触发
}

/**
* 打印标签之间的纯文本信息
*
* @param  {string} str 需要打印的元素的内容
*/
U.UF.CP.setInnerText = function (str) {//参数str  txt是内容   
    this.textContent = str; //获得元素的文本内容 = str
}
/**
* innerText与textContent的兼容处理
*/
U.UF.CP.setInnerTextGet = function () {
    return this.textContent; //获得元素的文本内容
}

/**
* 打印开始和结束标签之间的HTML
*
* @param  {string} str 字符串
*/
U.UF.CP.outerHtml = function (str) {
    var i,
        _this = U.selectEl(this), //i为变量
        _div = $$("div", { "innerHTML": str }).childNodes, //创建一个div 内容为str
        _create = $$("frag"); //  createDocumentFragment:创建一个 documentFragment 
    //循环插入
    for (i = 0; i < _div.length; i++) {//
        _create.appendChild(_div[i]); //在_create添加_div
    }
    _create.insertBefore(_create, this); //向列表中插入一个项目
    _this.remove(); //拷贝并删除本身
}
/**
* 打印开始和结束标签之间的HTML
*
* 给元素原型添加一个outerHtml方法
*/
U.UF.CP.outerHtmlGet = function () {
    var _copy = this.cloneNode(true); //克隆源元素
    var _div = $$("div", {}); //创建一个临时div,用于把克隆元素放入
    _div.appendChild(_copy); //div里面插入克隆元素
    return _div.innerHTML; /*如果不支持就使用innerhtml插入*/
}

/**
* 返回了元素上的样式表
*
* 给元素原型添加一个currentStyle方法
*/
U.UF.CP.getStyleGet = function () {
    return getComputedStyle(this, false); //返回的元素样式的属性
}

/**
* 可以将鼠标事件锁定在指定的元素上
*
* 给元素原型添加一个setCaptureGet方法
*/
U.UF.CP.setCapture = function () {
    return function () { //可以将鼠标事件锁定在指定的元素上
        window.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP);
    }
}

/**
* 释放鼠标捕获
* 给元素原型添加一个releaseCaptureGet方法
*/
U.UF.CP.releaseCapture = function () {//兼容火狐
    return function () {
        window.releaseEvents(Event.MOUSEMOVE | Event.MOUSEUP)
    } //释放鼠标捕获
}

/**
* 浏览器窗口被调整尺寸时发生
* @param  {function} fun 被调整的对象
*/
U.UF.CP.onresize = function (fun) {
    if (this.tagName) {//存在元素的标签名
        //设置Set事件
        var _position,
            _sizeelement = this.__SizeElement__; //自定义 __SizeElement__ 元素大小
        if (!_sizeelement || U.selectEl(_sizeelement).Parent() != this && fun) {//如果不存在SizeElement或者SizeElement的父级等于他本身并且存在el 往下执行
            _position = U.UF.EL.getStyle(this, "position");
            if (_position == "" || _position == "static") { this.style.position = "relative"; }
            _sizeelement = this.__SizeElement__ = $$("object", {//创建一个元素
                "onload": function () {
                    if (fun) {
                        _sizeelement.contentDocument.defaultView.onresize = function () {
                            fun();
                        }
                        // U.UF.C.apply(retElement, [[执行函数的事件]])
                        //retElement 将要绑定事件与属性的对象,如没有,可以传递null或者this,此处还需要优化,很多地方都会调用此函数,会导致速度降低。
                        //arr 时间和属性组成的参数数组 
                    }
                    else {
                        try {//try...catch语句将能引发错误的代码放在try块中,并且对应一个响应,然后有异常被抛出。
                            delete this.__SizeElement__;
                        } catch (e) { }
                    }
                }, //当触发onload时执行此函数
                "type": "text/html",
                "data": "about:blank",
                "style": {
                    "cssText": "display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1;visibility:hidden;margin:0;padding:0;"
                }
            }, this);
        }
        else {//如果上述条件不成立则直接往下执行
            if (fun) {
                _sizeelement.contentDocument.defaultView.onresize = function () { fun(); }
            }
            else {
                try {//try...catch语句将能引发错误的代码放在try块中,并且对应一个响应,然后有异常被抛出。
                    delete this.__SizeElement__;
                } catch (e) { }
            }
        }
    }
}
/**
* 浏览器窗口被调整尺寸时发生
*
* 给元素原型添加一个onresize方法
*/
U.UF.CP.onresizeGet = function () {
    try { //try...catch语句将能引发错误的代码放在try块中,并且对应一个响应,然后有异常被抛出。
        return this.__SizeElement__.contentDocument.defaultView.onresize;
    }
    catch (e) {
        return null;
    }
}

/**
* 代表事件的状态
* 比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
*/
U.UF.CP.eventGet = function () {//arguments.callee ->指向参数arguments对象的函数
    var _currentfun = arguments.callee;
    while (_currentfun.caller) { //一直往上寻找直到 寻找到顶层作用域 返回null 再往下执行
        _currentfun = _UDE.caller;
    }
    if (_currentfun.arguments[0]) { //对于火狐的兼容
        return _currentfun.arguments[0];
    }
    else {
        return null; //返回null
    }
}

/**
* 捕获当前事件作用的对象的兼容处理
*/
U.UF.CP.targetGet = function () {//支持firefox
    return event.target; //返回事件的目标节点(触发该事件的节点)
}

/**
* 获得键盘的按键码的兼容处理
*/
U.UF.CP.keyCodeGet = function () {
    return event.which; //获取按下的键盘按键Unicode值
}

/**
* onreadystatechange加载设置事件的兼容
*/
U.UF.CP.onreadystatechangeGet = function () {
    return this.onload; //当不兼容onreadystatechange的浏览器设置onreadystatechange的时候那么就相当于设置了onload
}

/**
* onreadystatechange加载获取事件的兼容
*/
U.UF.CP.onreadystatechange = function (cb) {
    this.onload = cb; //当不兼容onreadystatechange的浏览器获取onreadystatechange的时候那么就相当于获取onload
}

/**
* 特定事件返回对象在指定坐标下的位置。 outside 说明制定的位置在元素之外
*/
U.UF.CP.componentFromPoint = function () {
    return function () {
        var _position = U.UF.EL.getMousePosition();
        var _elinfo = U.UF.EL.getElementInfo(this);
        if ((_position["X"] > _elinfo["CW"] + _elinfo["TX"]) || (_position["Y"] > _elinfo["CH"] + _elinfo["TY"])) {
            return "outside";
        }
        return "";
    }
}

/**
* 在浏览器初始化的时候执行这个函数,给浏览器的兼容属性添加方法
*/
U.UF.CP.init = function () {
    //如果是html5浏览器,则执行判断内的内容,ie则不用进入下面内容。
    if (window.HTMLElement) {
        //注:   HTMLElement.prototype.__defineGetter__(event, fucntion)的作用是给指定的event设置得到的回调函数,如event=onmousewheel的时候,当我们给页面上任意的元素设置事件的时候会触发指定fucntion

        //当浏览器不支持onmousewheel滚轮事件的时候,给浏览器的全局HTMLElement设置滚轮事件,让页面上所有的元素都有onmousewheel这个事件
        //由于firefox不支持onmousewheel,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定onmousewheel这个事件
        /*检测浏览器是否支持onmousewheel这个方法,Safiri,火狐没有这个方法*/
        if (!("onmousewheel" in HTMLElement.prototype)) {
            //IE里面或者safiri的处理方法?
            if ("onwheel" in HTMLElement.prototype) {
                //滚轮事件兼容处理,分为get获取和set设置处理
                HTMLElement.prototype.__defineGetter__("onmousewheel", U.UF.CP.wheelGet); //元素onmousewheel的get处理
                HTMLElement.prototype.__defineSetter__("onmousewheel", U.UF.CP.wheel); //元素onmousewheel的set处理
            }
            //火狐的滚动处理
            else {
                window.addEventListener("DOMMouseScroll", function (e) {
                    //监控Scroll事件
                    var _fun = null,
                    _currentevent = e.srcElement; //e.srcElement当前事件的源
                    do {
                        _fun = U.selectEl(_currentevent).attr("onmousewheel") || _currentevent.onmousewheel;
                        _currentevent = U.selectEl(_currentevent).Parent();
                    }
                    while (!(_fun || !_currentevent)); //冒泡的顶部获取
                    if (_fun) {//如果存在_fun
                        if (U.UF.C.isString(_fun)) {//判断_fun 是否为字符串
                            _currentevent.onmousewheel = new Function(_fun);
                        }
                        U.UF.EV.stopDefault();    //阻止页面固定事件
                        //异步执行 解决卡死的bug
                        setTimeout(function () {
                            obj.call(this, e);
                        }, 0);
                    }
                }, false);
            }
        }


        //当浏览器不支持onreadystatechange的时候,给浏览器的全局HTMLElement设置onload,让页面上所有的元素都有onreadystatechange这个事件
        //由于chrome和friefox不支持onreadystatechange,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定onreadystatechange这个事件
        //        if (!("onreadystatechange" in HTMLElement.prototype)) {
        //            HTMLElement.prototype.__defineGetter__("onreadystatechange", U.UF.CP.onreadystatechangeGet); //onreadystatechange加载设置事件的兼容
        //            HTMLElement.prototype.__defineSetter__("onreadystatechange", U.UF.CP.onreadystatechange); //onreadystatechange加载设置事件的兼容
        //        }

        //当浏览器不支持innerText的时候,给浏览器的全局HTMLElement设置textContent,让页面上所有的元素都有innerText这个事件
        //由于低版本的firefox不支持innerText,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定innerText这个事件
        if (!("innerText" in HTMLElement.prototype)) {/*检测浏览器是否支持innerText这个方法*/
            HTMLElement.prototype.__defineGetter__("innerText", U.UF.CP.setInnerTextGet); //给元素原型添加一个innerText事件并且绑定U.UF.CP.setInnerText
            HTMLElement.prototype.__defineSetter__("innerText", U.UF.CP.setInnerText);
        }

        //当浏览器不支持outerHTML的时候,给浏览器的全局HTMLElement设置innerHTML,让页面上所有的元素都有outerHTML这个事件
        //由于低版本的firefox(FF7-)不支持outerHTML,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定outerHTML这个事件
        if (!("outerHTML" in HTMLElement.prototype)) {/*检测浏览器是否支持outerHTML这个方法*/
            HTMLElement.prototype.__defineGetter__("outerHTML", U.UF.CP.outerHtmlGet); //给元素原型添加一个outerHtml事件并且绑定U.UF.CP.outerHtml
            HTMLElement.prototype.__defineSetter__("outerHTML", U.UF.CP.outerHtml);
        }

        //当浏览器不支持currentStyle的时候,给浏览器的全局HTMLElement设置getComputedStyle事件,让页面上所有的元素都有currentStyle这个事件
        //由于低版本的firefox不支持currentStyle,这里利用__defineGetter__给HTMLElement绑定currentStyle这个事件
        if (!("currentStyle" in HTMLElement.prototype)) {/*检测浏览器是否支持currentStyle这个方法*/
            HTMLElement.prototype.__defineGetter__("currentStyle", U.UF.CP.getStyleGet); //给元素原型添加一个currentStyle事件并且绑定U.UF.CP.getStyle    
        }

        //当浏览器不支持setCapture的时候,给浏览器的全局HTMLElement设置captureEvents事件,让页面上所有的元素都有setCapture这个事件
        //由于firefox不支持setCapture,这里利用__defineGetter__给HTMLElement绑定setCapture这个事件
        if (!("setCapture" in HTMLElement.prototype)) {
            HTMLElement.prototype.__defineGetter__("setCapture", U.UF.CP.setCapture); //给元素原型添加一个setCapture事件并且绑定U.UF.CP.setCapture
        }

        //当浏览器不支持releaseCapture的时候,给浏览器的全局HTMLElement设置releaseEvents事件,让页面上所有的元素都有releaseCapture这个事件
        //由于firefox不支持releaseCapture,这里利用__defineGetter__给HTMLElement绑定releaseCapture这个事件
        if (!("releaseCapture" in HTMLElement.prototype)) {
            HTMLElement.prototype.__defineGetter__("releaseCapture", U.UF.CP.releaseCapture); //给元素原型添加一个releaseCapture事件并且绑定U.UF.CP.releaseCapture
        }

        //当浏览器不支持onresize的时候,给浏览器的全局HTMLElement设置focus,让页面上所有的元素都有onresize这个事件
        //由于低版本的firefox不支持onresize,这里利用__defineGetter__和__defineSetter__给HTMLElement绑定onresize这个事件
        if (!("onresize" in HTMLElement.prototype) || !(U.UF.CI.getBrowser().browser == "msie")) { /*检测浏览器是否支持onfocus事件*/
            HTMLElement.prototype.__defineGetter__("onresize", U.UF.CP.onresizeGet); //给元素原型添加一个onresize事件并且绑定U.UF.CP.onresize
            HTMLElement.prototype.__defineSetter__("onresize", U.UF.CP.onresize);
        }
        /*检测浏览器是否支持componentFromPoint事件*/
        if (!("componentFromPoint" in HTMLElement.prototype)) {
            HTMLElement.prototype.__defineGetter__("componentFromPoint", U.UF.CP.componentFromPoint); //当获取元素的componentFromPoint时候出发该函数
        }

        //当浏览器不支持event的时候,给浏览器的全局HTMLElement设置releaseEvents,让页面上所有的元素都有event这个事件
        //由于firefox不支持event,这里利用__defineGetter__给HTMLElement绑定event这个事件
        if (!("event" in window.constructor.prototype)) { /*检测浏览器是否支持event事件*/
            window.constructor.prototype.__defineGetter__("event", U.UF.CP.eventGet); //给元素原型添加一个event事件并且绑定U.UF.CP.event
        }
        //给window.event添加兼容属性方法
        if (window.Event.prototype) {
            //当浏览器不支持srcElement的时候,给浏览器的全局HTMLElement设置target事件,让页面上所有的元素都有srcElement这个事件
            //由于firefox不支持srcElement,这里利用__defineGetter__给HTMLElement绑定srcElement这个事件
            if (!("srcElement" in window.Event.prototype)) {/*检测浏览器是否支持srcElement事件*/
                window.Event.__defineGetter__("target", U.UF.CP.targetGet); //给元素原型添加一个target事件并且绑定U.UF.CP.target
            }
            //当浏览器不支持keyCode的时候,给浏览器的全局HTMLElement设置which事件,让页面上所有的元素都有keyCode这个事件
            //由于firefox不支持keyCode,这里利用__defineGetter__给HTMLElement绑定keyCode这个事件
            if (!("keyCode" in window.Event.prototype) && window.Event.__defineGetter__) {
                window.Event.__defineGetter__("keyCode", U.UF.CP.keyCodeGet); //给元素原型添加一个keyCode事件并且绑定U.UF.CP.keyCheck
            }
        }
    }
}

//#region querySelector 兼容处理

U.UF.C.style; //防止选择器创建多个样式style

/**
* querySelectorAll 兼容
*
* @param  {string} 搜索的内容
* @param  {element} 搜索的元素区域
*/
document.querySelectorAll = document.querySelectorAll || function (str, el) {
    var _addstyle = U.UF.C.style, //判断是否已经添加了上style识别样式
        _returnarr = [], //创建一个空的数组
        _firstchild = document.documentElement.firstChild, //document.documentElement的第一个子元素
        _arr = (el || document).all, //搜索区域
        i = _arr.length; //_arr的长度

    //添加的style link
    try {
        _addstyle.styleSheet.cssText = str + "{q:1}";
    }
    catch (e) {
        U.UF.C.style = $$("style", {//U.UF.C.style:防止选择器创建多个样式style
            "type": "text/css",
            "styleSheet": {
                "cssText": str + "{q:1}"
            }
        }, _firstchild);
    }
    //全局筛选
    while (i--) {
        if (_arr[i].currentStyle.q) {
            _returnarr.unshift(_arr[i]);
        }
    }
    return _returnarr;
};

/**
* querySelector 兼容
*
* @param  {number} 搜索的内容
*/
document.querySelector = document.querySelector || function (num) {//返回文档中匹配指定 CSS 选择器的一个元素
    var _num = document.querySelectorAll(num);
    if (_num.length) {//如果_num存在
        return _num[0]; //返回_num[0]
    }
    else {//不存在
        return null; //返回null
    }
};

/**
* 选择元素区域 自定义搜索元素选择函数
*
* @param  {string} 搜索的内容
* @param  {object} 搜索的元素
*/
U.UF.CP.selectorElement = function (str, el) {
    var _ishasid = (el.id === "" && el != document), //判断是否支持选择器
        _query = $$("div").querySelectorAll;

    if (_ishasid) {//如果支持
        el.id = el.uniqueID; //uniqueID : 绝对唯一地标识一个 HTML 元素
    }
    try { //尝试执行代码块
        if (_query) {//如果浏览器支持querySelectorAll ,那么直接使用浏览器的
            return (el || document).querySelectorAll((el.id ? ("#" + el.id + " ") : " ") + str, el);
        }
        //否则调用上面自定义的方法
        else {
            return document.querySelectorAll((el.id ? ("#" + el.id + " ") : " ") + str, el);
        }
    }
    catch (e) {//捕获错误的代码块
        return null;
    }
    finally {//无论 try / catch 结果如何都会执行的代码块
        if (_ishasid) {
            el.id = "";
        }
    }
}

//#endregion

//#region 手机兼容处理,只要引用了uform框架,会自动使手机在滑动的过程中不会触发点击事件

/**
*  手机点击处理
*/
U.UF.CP.touch = function () {
    //这里有个bug如果多次引用uform的时候这里的事件会注册监视多次
    if (U.UF.C.touchstart) {
        U.UF.EV.delElementEvent("touchstart", document, U.UF.C.touchstart, true);
    }
    //监视touchstart,注册函数事件  U.UF.EV.addElementEvent(事件名称,添加事件的元素,事件触发后调用的函数,指定事件是否在捕获或冒泡阶段执行)
    U.UF.EV.addElementEvent("touchstart", document, U.UF.C.touchstart, true);
}

/**
*  touchstart处理
*/
U.UF.C.touchstart = function () {
    var i,
        _eventsrc = event.srcElement; //时间触发的元素
    //默认触发的时候是没有移动的状态
    U.UF.C.ismove = null;
    //停止事件分发
    U.UF.EV.stopBubble();
    //移除start事件事件取消,防止下面直接出发touch事件的时候给重复监听
    U.UF.EV.delElementEvent("touchstart", document, U.UF.C.touchstart, true);
    //直接执行touchstart事件
    U.UF.EV.simulatePhoneTouch(_eventsrc, "touchstart");
    //取消后重新添加事件进去 
    U.UF.EV.addElementEvent("touchstart", document, U.UF.C.touchstart, true);
    //监视在鼠标移动的处理
    U.UF.EV.addElementEvent("touchmove", document, U.UF.C.touchmove);
    //end事件等待
    U.UF.EV.addElementEvent("touchend", document, U.UF.C.touchend, true);
}

/**
*  touchmove处理
*/
U.UF.C.touchmove = function () { //移动监视
    U.UF.C.ismove = true; //设置鼠标在移动
    U.UF.EV.delElementEvent("touchmove", document, U.UF.C.touchmove); //移除鼠标移动事件
    U.UF.EV.simulatePhoneTouch(event.srcElement, "touchmove"); //执行事件touch移动的处理
    U.UF.EV.stopBubble(); //停止冒泡处理
}

/**
*  touchend处理
*/
U.UF.C.touchend = function () {
    U.UF.EV.delElementEvent("touchend", document, U.UF.C.touchend, true); //touchend抓取成功后的处理
    U.UF.EV.stopBubble(); //移除事件
    //如果用户的touchstart后没有处理touchmove事件,那么允许用户出发touchend事件
    if (!U.UF.C.ismove) {
        U.UF.EV.simulatePhoneTouch(event.srcElement, "touchend"); //触发touchend事件
    }
}

//#endregion;
///<jscompress sourcefile="Cookie.js" />
//处理Cookie:
Namespace.register("U.UF.Cookie");

/**
*在www.boomyun.com等其他网站调用www.1473.cn的后台数据时,动态植入js文件,js文件会把1473的cookie带到自己的网站中.实现跨域功能
*在iframe中调用此函数,会把主页的cookie传递到子域, 跨域加载cookie,1473子域用,其他跨域不能用,为了兼容ie6,ie7,暂时未用。
*
* @param  {string} 跨域的url
* @param  {function} 成功记载后的回调函数
*/
U.UF.Cookie.crossDomain = function (url, cb) {
    //跨域的时候由于cookie出现问题
    U.UF.DL.asynLoadJs({ "src": url }, cb);
}

/**
* 设置cookie
*
* @param  {string || object} cookie 字符串或者cookie集合。参见例一,例三。
* 
* @param  {object} cookie 的key
----------path: null, //cookie地址
----------domain: null, //cookie域
----------expires: 365, //cookie过期时间
----------secure: null //cookie来源
* @return  {string}
*例一:U.UF.Cookie.set("usestudiossso=UserId=aa&UserName=zhangsan");net java模式
*例二:U.UF.Cookie.set("15hulianwang=userid=123456&username=zhangsan");net java模式
*例三:U.UF.Cookie.set({15hulianwang:{userid:123456,username:'zhangsan'}});nodejs模式
*/
U.UF.Cookie.set = function (key, att) {
    var i, //循环初始化
        j, //循环初始化
        k = 0, //用于计数
        _cookiestr = ""; //最终的cookie字符串
    //如果key是字符串,则直接设置cookie,如果为集合,则转换为字符串进行处理。
    if (U.UF.C.isString(key)) {//判断设置的是否是字符串 
        _cookiestr = key;
        document.cookie = U.UF.Cookie.setProperty(att, key);
    }
    //用json的方式设置网页的cookie,循环拼接cookie字符串
    else {
        for (i in key) {
            _cookiestr = i + "=";
            for (j in key[i]) {
                //把集合拆分成字符串。
                //如果k>0,则添加&号分割符
                if (k > 0) {
                    _cookiestr += "&";
                }
                _cookiestr += j + "=" + encodeURIComponent(key[i][j]);
                k++;
            }
            //cookie处理
            document.cookie = U.UF.Cookie.setProperty(att, _cookiestr);
        }
    }
    return document.cookie;
}

/**
* 设置指定参数(添加cookie属性)
*
* @param  {object} cookie 的key
----------path: null, //cookie地址
----------domain: null, //cookie域
----------expires: 365, //cookie过期时间
----------secure: null //cookie来源
* @param  {string} 需要写入的cookie usestudio=aa=cc
* @return  {string} 返回写入的cookie值
*/
U.UF.Cookie.setProperty = function (key, val) {
    var i, //循环初始化
        _pj, //记录循环时的键值
        _time, //时间,用户修改时间
        _cookie = {//cookie对象值
            path: "/", //cookie地址
            domain: document.domain, //cookie域
            expires: 365, //cookie过期时间
            secure: null //cookie来源
        };
    //一般不传递第二个参数,这里为空会报错,所以转换为集合
    key = key || {};
    for (i in _cookie) { //循环设置
        //不去找原型,直接找_cookie中定义的变量和方法
        if (i == "expires" && (key[i] || _cookie[i])) { //时间过期处理
            _time = new Date();
            //如果用户设置了时间,则用用户的时间,否则默认过期时间为一年
            var _etime = (key[i] || _cookie[i]) * 24 * 60 * 60 * 1000;
            _time.setTime(_time.getTime() + _etime); //时间变化处理
            key[i] = _time.toUTCString();
        }
        //判断是否设置cookie属性,如果用户不设置,系统默认为null,则不设置,例如secure: null 
        if (key[i] || _cookie[i]) {
            //如果用户设置属性为null,则用系统的,否则用用户设置的属性
            if (key[i] == null) {
                _pj = _cookie[i];
            }
            else {
                _pj = key[i];
            }
            //拼接cookie。
            val += "; " + i + "=" + _pj; //添加cookie
        }
    };
    return val; //返回cookie
}

/**
* 移除cookie(删除)
*
* @param  {string} cookie 的key
* @return  {string}
*/
U.UF.Cookie.del = function (key) {
    var i, //循环初始化
        _array, //分割后的建值数组
        _key = "", //删除指定的cookie
        _cookies = document.cookie.split("; "); //cookie值
    //过滤指定的cookie值
    for (i = 0; i < _cookies.length; i++) {
        _array = _cookies[i].split("=");
        //如果符合用户传递的cookie的key值,则转换为字符串
        if (!key || _array[0] == key) {
            //多cookie情况下,用分号分割,否则不分割
            var _cut = _key.length ? "; " : "";
            _key += _cut + _array[0] + "=";
        }
    }
    //删除指定的cookie
    if (_key) {
        U.UF.Cookie.set(_key, { expires: -1 });
    }
    else {
        console.log("not found cookie!");
    }
}

/**
* 功能:获取用户指定的Cookie值
描述:浏览器cookie形如:"pgv_pvid=3156364456; usestudiosso=userid=72854d28-f45c-48d7-92b7-3cd933e03022&username=13928417148&Loginid=fd02976d-993b-4437-bbd9-5efa99802c8f&userstamp=1364812396; __qc_wId=563; amvid=319501000bca68c1adab006842344f44"
第一步:根据分号拆分成数组.
第二部:按照"="拆分
第三部:找到"usestudiosso",usestudiosso=userid=72854d28-f45c-48d7-92b7-3cd933e03022&username=13928417148&Loginid=fd02976d-993b-4437-bbd9-5efa99802c8f&userstamp=1364812396
第四步:去掉"usestudiosso",得到userid=72854d28-f45c-48d7-92b7-3cd933e03022&username=13928417148&Loginid=fd02976d-993b-4437-bbd9-5efa99802c8f&userstamp=1364812396
参数一:UKY为cookie名字,云端cookie名为:"usestudiosso"
*
* @param  {string} 获取cookie的key对应的值 如usestudio=aa=ff&ss=aa 的usestudio里的 aa=ff&ss=aa
* @param  {string} aa=ff&ss=aa里面的aa对应的值 [ff]
* @return  {string, array} 上述参数里说明返回 
---------第二个参数不存在的时候返回string
---------第二个参数存在的时候返回array
*/
U.UF.Cookie.get = function (key, val) {
    var i, //循环初始化
        _valuearray, //储存字符串的数组
        _value = "", //返回值
        _cookies = document.cookie.split("; "); //从cookie中获取指定的cookie集
    //循环拆分cookie
    for (i = 0; i < _cookies.length; i++) {
        //以“=”的形式拆分成数组
        _valuearray = _cookies[i].split("=");
        //如果找到名为"usestudiosso"的cookie,则
        if (_valuearray[0] == key) {
            _valuearray.splice(0, 1);
            _value = _valuearray.join("=");
            break;
        } //生成指定的Cookie
    }
    if (val) {//从指定的cookie集里获取cookie值
        _cookies = _value.split("&");
        _value = [];
        for (i = 0; i < _cookies.length; i++) {
            _valuearray = _cookies[i].split("=");
            //获取指定的cookie值
            if (_valuearray[0] == val) {
                _value.push(decodeURIComponent(_valuearray[1]));
            }
            //判断是否是指定的cookie存在 
            else if (_valuearray[1] == val) {
                return true;
            }
        }
    }
    return (_value.length ? _value : false);
}
;
///<jscompress sourcefile="CrossDomain.js" />
/*
此处为1473跨域文件夹 利用此文件函数实现1473跨域
所有需要使用ajax跨域的后台 包括 user.1473.cn(用户系统后台) disk.1473.cn(网盘系统后台) friend.1473.cn(好友系统后台) cd.1473.cn(数据库系统后台)
*/
Namespace.register("U.UF.CD");

//#region 跨域全局变量

//跨一级域的两个跨域页面, 一个是用于跨域获取数据的,一个是用于跨域获取页面数据的
//数据的crossdomain
U.UF.CD.AJAXCROSSDOMAIN = "http://www.1473.cn/DataCrossdomain.htm"; //外域引入1473跨域文件

//整个1473页面的crossdomain
U.UF.CD.PAGECROSSDOMAIN = "http://www.1473.cn/PageCrossdomain.htm"; //跨域获取1473桌面文件

//好友系统页面
U.UF.CD.FRIENDINDEX = "http://friend.1473.cn/friend.aspx"; //跨域获取1473桌面文件

//用户系统页面
U.UF.CD.USERINDEX = "http://user.1473.cn/user.aspx"; //跨域获取1473桌面文件

//网盘系统页面
U.UF.CD.DISKINDEX = "http://disk.1473.cn/disk.aspx"; //跨域获取1473桌面文件

//office系统页面
U.UF.CD.OFFICEINDEX = "http://usoffice.1473.cn/office.aspx"; //跨域获取1473桌面文件


//跨域到main去获取数据的iframe页面,和上面的区别是,这个是真正的跨域页面数组,上面只是给一级域跨域的方案,最终上面页面也是应用了这个函数
U.UF.CD.AJAXIFRAMES = [
//主域名跨域地址
      {
      "id": "U_Main", //跨域iframe的id
      "url": "http://main.1473.cn/Crossdomain.htm" //跨域iframe的地址
  },
//网盘系统跨域地址
      {
      "id": "U_Disk", //跨域iframe的id
      "url": "http://disk.1473.cn/Crossdomain.htm" //跨域iframe的地址
  },
//好友系统跨域地址
      {
      "id": "U_Friend", //跨域iframe的id
      "url": "http://friend.1473.cn/Crossdomain.htm" //跨域iframe的地址
  },
//好友系统跨域地址
      {
      "id": "U_User", //跨域iframe的id
      "url": "http://user.1473.cn/Crossdomain.htm" //跨域iframe的地址
  },
//cd.1473.cn跨域地址
      {
      "id": "U_CD", //跨域iframe的id
      "url": "http://cd.1473.cn/Crossdomain.htm" //跨域iframe的地址
  }
];

//跨域获取页面数据的url
U.UF.CD.STATION = "http://www.1473.cn/default.aspx";

//#endregion

//#region ajax跨域方案

/**
* 加载跨域文件  异步加载iframe跨域请求1473项目加载请求
* @param  {function} 加载成功回调函数
* @param  {element}  用户使用U.A.Request时需要时间,则做loading效果
*/
U.UF.CD.loadAjaxCrossDomain = function (cb, loadingel) {
    var i,
        _iframe, //创建的iframe
        _iframeid, //iframe的名字
        _len = { length: U.UF.CD.AJAXIFRAMES.length },
        _parentel = U.selectEl("#usestudio_server")[0] || U.selectEl("body")[0], //跨域iframe添加的位置
        _crossobj = U.UF.CD.AJAXIFRAMES; //需要跨域的数组
    //1473站内同域跨域
    if (document.domain.indexOf("1473.cn") > -1) {
        //循环添加跨域元素
        for (i = 0; i < _crossobj.length; i++) {
            try {
                _iframeid = _crossobj[i].id; //获取加载iframe的id和name
                //如果iframe已经存在,表示已经加载了跨域iframe,该跨域已经加载处理
                if (window[_iframeid] && window[_iframeid].location) { //判断跨域是否已经加载
                    //由于在加载的过程中 iframe的href获取不到,也说明还没有加载成功,同理如果获取到值,同事值等于U.UF.CD.AJAXCROSSDOMAIN,那么就是成功调用
                    if (window[_iframeid].location.href == _crossobj[i].url) {
                        //设置域名加载成功函数
                        U.UF.CD.asynLoadAjaxCrossDomain($("#" + _iframeid)[0], cb, _len);
                    }
                }

                //创建一个ajax跨域的iframe 
                _iframe = $$("iframe", { "id": _iframeid, "name": _iframeid, "width": 0, "height": 0, "style": { "display": "none" }, "src": _crossobj[i].url });

                //跨域回调设置
                U.UF.DL.iframeLoad(_iframe, function () {
                    U.UF.CD.asynLoadAjaxCrossDomain(_iframe, cb, _len);
                });
                _parentel.appendChild(_iframe); //把ajax跨域放在页面
                //跨域加载需要时间,可以传递一个loading图标。
                if (loadingel) {
                    U.UF.DL.loading(loadingel);
                }
            }
            catch (e) { }
        }

    }
    //非1473域的跨域方式
    else {
        //如果跨域的iframe没有调用,那么就调用跨域的iframe。
        U.UF.CD.thirdPartyLoadAjaxCrossDomain(cb, loadingel); //初始化1473
    }
}

/**
* iframe加载成功后,异步加载跨域
*
* @param  {object} 当前跨域集
* @param  {function} 成功回调
* @param  {array} 所有的跨域集
* @return {boolean} 是否已经成功过回调
*/
U.UF.CD.asynLoadAjaxCrossDomain = function (iframe, cb, len) { //加载跨域文件
    var _window = iframe.contentWindow; //获取iframe的域
    try {
        _window.name = iframe.id; //设置当前的iframe的name,因为在ie7下无法使用
    }
    catch (e) { }
    len.length--;
    //判断是否有回调函数
    if (U.UF.C.isFunction(cb) && len.length == 0) {
        cb();
    }
}

/**
* 非1473跨域ajax的加载
*
* @param  {function} 加载回调
* @param  {element} loading元素
*/
U.UF.CD.thirdPartyLoadAjaxCrossDomain = function (cb, loading) {
    var _el, //iframe元素
        _parentel = U.selectEl("#usestudio_server")[0] || U.selectEl("body")[0];
    //判断跨域的iframe是否已经在加载了,如果加载了
    if (window["U_Domain"]) {
        //由于在加载的过程中 iframe的href获取不到,也说明还没有加载成功,同理如果获取到值,同事值等于U.UF.CD.AJAXCROSSDOMAIN,那么就是成功调用
        if (window["U_Domain"].location.href == U.UF.CD.AJAXCROSSDOMAIN && U.UF.C.isFunction(cb)) {
            cb();
        }
    }
    //如果没有加载跨域的ajax的iframe
    else {
        //创建一个iframe元素
        _el = $$("iframe", {
            "id": "U_Domain",
            "name": "U_Domain",
            "width": 0,
            "height": 0,
            "style": {
                "display": "none"
            }
        }, _parentel);
        //等待iframe加载,加载成功通知
        U.UF.DL.iframeLoad(_el, function () {
            //判断是否有回调函数
            if (U.UF.C.isFunction(cb)) {
                cb();
            }
        });
        //如果加载的过程需要loading的处理
        if (loading) {
            U.UF.DL.loading(loading); //加载1473loading
        }
        _el.src = U.UF.CD.AJAXCROSSDOMAIN; //这个是跨iframe的地址
    }
}

//#endregion

//#region 页面跨域方案

/**
* 跨域引用1473,把1473整个下载到项目中,利用该方案可以把整个1473的项目引入到其他任何项目里,包括跨一级域
*
* @param  {element} 加载1473时给其他网站的loanding元素
* @param  {function} 加载1473成功的回调函数
* @param  {bool} 是否加载1473桌面,如果不是,则只加载窗体。任务管理系统需要我们的桌面
*/
U.UF.CD.loadPageCrossDomain = function (cb, loading, b) {
    var _iframe;
    //判断是否已经加载了跨域的iframe
    if (!$("#usestudio_server")[0]) {
        //创建最大的div元素,用于把加载的数据写入该元素内
        var _el = $$("div", { "id": "usestudio_server", "className": "usestudio_server", "__top__": "false" }, document.body); //点击后z-index不会增加,防止覆盖用户
        //1473域加载1473平台
        if (document.domain == "1473.cn") {
            //创建一个iframe,指向1473的主页
            _iframe = $$("iframe", { "width": 0, "height": 0, "style": { "display": "none"} }, U.selectEl("body")[0]);
            //如果加载的过程需要loading的处理
            if (loading) {
                U.UF.DL.loading(loading); //加载1473loading
            }
            //等待iframe加载
            U.UF.DL.iframeLoad(_iframe, U.UF.C.apply(null, function () {
                U.UF.CD.asynLoadPageCrossDomain(_iframe, loading, cb, b);
            }));
            _iframe.src = U.UF.CD.STATION;
        }
        //非1473加载
        else {
            //创建一个iframe,指向1473的跨域获取页面数据的页面
            _iframe = $$("iframe", { "id": "U_CDomain", "name": "U_CDomain", "width": 0, "height": 0, "style": { "display": "none"} }, document.body);
            //等待iframe加载,加载成功后获取数据
            U.UF.DL.iframeLoad(_iframe, function () {
                //跨域iframe之间的跨域调用数据
                new U.UF.EV.message(function (arr) {
                    /*
                    *  arr是一个数组 里面的数据包含 0:获取的页面的innerhtml值 1:跨域cookie的传参
                    */
                    U.selectEl(_iframe).remove(); //移除获取值后的iframe
                    //设置cookie使用
                    var _content = U.selectEl("#usestudio_server")[0]; //获取加载的位置
                    _content.outerHTML = arr; //把数据添加到当前页面
                    //如果应用了ufromd的那么数据出来后需要通过原本页面的window.onload进行加载,否则页面的数据没有初始化会有问题
                    if (U.MD.D) {
                        U.MD.D.Load(cb);
                    }
                    //如果有回调函数那么直接回调
                    else if (U.UF.C.isFunction(cb)) {
                        cb();
                    }
                }, true, "pagedomain", "U_CDomain").post("", "pagedomain");
            });
            _iframe.src = U.UF.CD.PAGECROSSDOMAIN; //加载跨页面获取的链接
        }
    }
    else {
        cb();
    }
}

/*
* 加载1473整体
*
* @param  {element} 当前加载的iframe
* @param  {element} 需要loading的元素
* @param  {element} 加载的位置
* @param  {bool} 是否加载1473桌面,如果不是,则只加载窗体。任务管理系统需要我们的桌面
*/
U.UF.CD.asynLoadPageCrossDomain = function (iframe, loading, cb, b) {
    var i,
        _js,
        _document,
        _html,
        _windows = iframe.contentWindow, //跨域的iframe的域window层
        _cookie = _windows.document.cookie.split("="); //专门用于跨域记录1473的cookie
    ;
    if (_cookie[1] == "") { //删除cookie的值
        U.UF.Cookie.del(_cookie[0]);
    }
    //如果在和后台交互的过程设置了cookie,那么这里需要设置
    else {
        U.UF.Cookie.set(_cookie[2]);
    }
    var _content = U.selectEl("#usestudio_server")[0]; //获取加载的位置
    _html = U.selectEl("#U_MD_Home", _windows.document)[0].outerHTML; ///得到iframe整个1473的内容数据 b === true ? "body" : 
    //得到值后把iframe清空的方式,不清空会出现js的报错
    try {
        //新建一个doc层清空法,在高版本的chrome下会出现报错
        _document = _windows.document.open();
    }
    //直接得到docment清空法
    catch (e) {
        _document = _windows.document;
    }
    //清空
    _document.write = "";
    _document.close(); //关闭document层
    U.selectEl(iframe).remove(); //移除获取值后的iframe
    _content.innerHTML = _html; //把数据添加到当前页面
    //加载js
    _js = U.selectEl("script", _content);
    for (i = 0; i < _js.length; i++) {
        U.UF.DL.asynLoadJs({ src: _js[i].src, "charset": "utf-8", "type": "text/javascript" })
    }
    //如果应用了ufromd的那么数据出来后需要通过原本页面的window.onload进行加载,否则页面的数据没有初始化会有问题
    if (U.MD.D) {
        U.MD.D.Load(cb)
    }
    //如果有回调函数那么直接回调
    else {
        U.UF.CD.loadApplication(cb);
    }
}

/**
* 加载user 、 friend 、disk的js
*/
U.UF.CD.loadApplication = function (cb) {
    if (document.domain == "1473.cn") {
        var _len = 4; //这个是加载应用的数量
        //加载成功的回调函数
        var _fun = function () {
            _len--;
            if (_len == 0) {
                if (U.UF.C.isFunction(cb)) {
                    cb();
                }
            }
        };
        //加载用户
        U.UF.CD.loadUser(_fun);
        //加载硬盘
        U.UF.CD.loadDisk(_fun);
        //加载好友
        U.UF.CD.loadFriend(_fun);
        //加载office系统
        U.UF.CD.loadOffice(_fun);
    }
    else if (U.UF.C.isFunction(cb)) {
        cb();
    }
}

/*
* 加载用户模块
*
* @param  {function} 创建成功后的回调函数
*/
U.UF.CD.loadUser = function (cb) {
    //创建一个iframe,指向1473的主页
    var _iframe = $$("iframe", { "width": 0, "height": 0, "style": { "display": "none"} }, U.selectEl("body")[0]);
    //等待iframe加载
    U.UF.DL.iframeLoad(_iframe, U.UF.C.apply(null, function () {
        U.UF.CD.asynLoadUser(_iframe, cb);
    }));
    _iframe.src = U.UF.CD.USERINDEX; //加载好友
}

/*
* 异步加载用户模块
*
* @param  {function} 创建好友
*/
U.UF.CD.asynLoadUser = function (iframe, cb) {
    var i,
        _document,
        _html,
        _windows = iframe.contentWindow //跨域的iframe的域window层
    ;
    _html = U.selectEl("body", _windows.document)[0].innerHTML; ///得到iframe整个1473的内容数据 b === true ? "body" : 
    //得到值后把iframe清空的方式,不清空会出现js的报错
    try {
        //新建一个doc层清空法,在高版本的chrome下会出现报错
        _document = _windows.document.open();
    }
    //直接得到docment清空法
    catch (e) {
        _document = _windows.document;
    }
    //清空
    _document.write = "";
    _document.close(); //关闭document层
    U.selectEl(iframe).remove(); //移除获取值后的iframe
    //把数据添加到当前页面
    if ($("#U_MD_Home")[0]) {
        U.selectEl("#U_MD_Home")[0].innerHTML += _html;
    }
    else {
        U.selectEl("body")[0].innerHTML = _html;
    }
    if (U.UF.C.isFunction(cb)) {
        cb();
    }
}

/*
* 加载网盘模块
*
* @param  {function} 创建成功后的回调函数
*/
U.UF.CD.loadDisk = function (cb) {
    //创建一个iframe,指向1473的主页
    var _iframe = $$("iframe", { "width": 0, "height": 0, "style": { "display": "none"} }, U.selectEl("body")[0]);
    //等待iframe加载
    U.UF.DL.iframeLoad(_iframe, U.UF.C.apply(null, function () {
        U.UF.CD.asynLoadDisk(_iframe, cb);
    }));
    _iframe.src = U.UF.CD.DISKINDEX;

}

/*
* 加载网盘模块异步
*
* @param  {function} 创建成功后的回调函数
*/
U.UF.CD.asynLoadDisk = function (iframe, cb) {
    var i,
        _document,
        _html,
        _windows = iframe.contentWindow //跨域的iframe的域window层
    ;
    _html = U.selectEl("body", _windows.document)[0].innerHTML; ///得到iframe整个1473的内容数据 b === true ? "body" : 
    //得到值后把iframe清空的方式,不清空会出现js的报错
    try {
        //新建一个doc层清空法,在高版本的chrome下会出现报错
        _document = _windows.document.open();
    }
    //直接得到docment清空法
    catch (e) {
        _document = _windows.document;
    }
    //清空
    _document.write = "";
    _document.close(); //关闭document层
    U.selectEl(iframe).remove(); //移除获取值后的iframe
    if ($("#U_MD_Home")[0]) {
        U.selectEl("#U_MD_Home")[0].innerHTML += _html; //把数据添加到当前页面
    }
    else {
        U.selectEl("body")[0].innerHTML = _html; //把数据添加到当前页面
    }
    if (U.UF.C.isFunction(cb)) {
        cb();
    }
}

/*
* 加载好友模块
*
* @param  {function} 创建成功后的回调函数
*/
U.UF.CD.loadFriend = function (cb) {
    //创建一个iframe,指向1473的主页
    var _iframe = $$("iframe", { "width": 0, "height": 0, "style": { "display": "none"} }, U.selectEl("body")[0]);
    //等待iframe加载
    U.UF.DL.iframeLoad(_iframe, U.UF.C.apply(null, function () {
        U.UF.CD.asynLoadFriend(_iframe, cb);
    }));
    _iframe.src = U.UF.CD.FRIENDINDEX;
}

/*
* 加载好友模块异步
*
* @param  {function} 创建成功后的回调函数
*/
U.UF.CD.asynLoadFriend = function (iframe, cb) {
    var i,
        _document,
        _html,
        _windows = iframe.contentWindow //跨域的iframe的域window层
    ;
    _html = U.selectEl("body", _windows.document)[0].innerHTML; ///得到iframe整个1473的内容数据 b === true ? "body" : 
    //得到值后把iframe清空的方式,不清空会出现js的报错
    try {
        //新建一个doc层清空法,在高版本的chrome下会出现报错
        _document = _windows.document.open();
    }
    //直接得到docment清空法
    catch (e) {
        _document = _windows.document;
    }
    //清空
    _document.write = "";
    _document.close(); //关闭document层
    U.selectEl(iframe).remove(); //移除获取值后的iframe
    if ($("#U_MD_Home")[0]) {
        U.selectEl("#U_MD_Home")[0].innerHTML += _html; //把数据添加到当前页面
    }
    else {
        U.selectEl("body")[0].innerHTML = _html; //把数据添加到当前页面
    }
    if (U.UF.C.isFunction(cb)) {
        cb();
    }
}


/*
* 加载office模块
*
* @param  {function} 创建成功后的回调函数
*/
U.UF.CD.loadOffice = function (cb) {
    //创建一个iframe,指向1473的主页
    var _iframe = $$("iframe", { "width": 0, "height": 0, "style": { "display": "none"} }, U.selectEl("body")[0]);
    //等待iframe加载
    U.UF.DL.iframeLoad(_iframe, U.UF.C.apply(null, function () {
        U.UF.CD.asynLoadOffice(_iframe, cb);
    }));
    _iframe.src = U.UF.CD.OFFICEINDEX;
}

/*
* 加载好友模块异步
*
* @param  {function} 创建成功后的回调函数
*/
U.UF.CD.asynLoadOffice = function (iframe, cb) {
    var i,
        _document,
        _html,
        _windows = iframe.contentWindow //跨域的iframe的域window层
    ;
    _html = U.selectEl("body", _windows.document)[0].innerHTML; ///得到iframe整个1473的内容数据 b === true ? "body" : 
    //得到值后把iframe清空的方式,不清空会出现js的报错
    try {
        //新建一个doc层清空法,在高版本的chrome下会出现报错
        _document = _windows.document.open();
    }
    //直接得到docment清空法
    catch (e) {
        _document = _windows.document;
    }
    //清空
    _document.write = "";
    _document.close(); //关闭document层
    U.selectEl(iframe).remove(); //移除获取值后的iframe
    if ($("#U_MD_Home")[0]) {
        U.selectEl("#U_MD_Home")[0].innerHTML += _html; //把数据添加到当前页面
    }
    else {
        U.selectEl("body")[0].innerHTML = _html; //把数据添加到当前页面
    }
    if (U.UF.C.isFunction(cb)) {
        cb();
    }
}

//#endregion
;
///<jscompress sourcefile="Date.js" />
//#region

Namespace.register("U.UF.D");

//把2018/01/01 01:01:01转换为"2017-11-06 09:24:32"
//把2018-01-01 01:01:01时间转换为数组格式[2018,01,01,01,01,01]
//方便用户自己拼接不同格式的时间。
//参数一:时间格式  
//   1、javascrpt 自带的时间格式 datetime类型 Sun Mar 04 2018 18:45:54 GMT+0800 (中国标准时间)
//   2、sqlserver 时间格式 /Date(1364812396843)/
//   3、mongodb 时间格式 2018/01/01 01:01:01
//   4、mysql 时间格式 2018-01-01 01:01:01
//   5、nodejs的json时间"2018-03-04T11:14:27.878Z"
U.UF.D.formatDateToArray = function (date) {
    var _datearr = [];
    //javascript自带时间无需处理,并且不是string类型
    if (typeof date == "string") {
        if (date.indexOf("Date") > -1) { //sqlserver 格式处理
            date = new Date(parseInt(date.match(/[0-9]+/g)[0])); //正则会把2-4种时间格式转换为第一种格式. 2018/01/01 01:01:01 => 20180101010101
        }
        else {
            date = new Date(date);
        }
    }
    return [
            date.getFullYear(),
            date.getMonth() + 1, //月份加1
            date.getDate(),
            date.getHours(),
            date.getMinutes(),
            date.getSeconds()
    ];
}

//把数据库的时间戳转换成可读时间
//参数一:时间格式  
//   1、javascrpt 自带的时间格式 datetime类型 Sun Mar 04 2018 18:45:54 GMT+0800 (中国标准时间)
//   2、sqlserver 时间格式 /Date(1364812396843)/
//   3、mongodb 时间格式 2018/01/01 01:01:01
//   4、mysql 时间格式 2018-01-01 01:01:01
//   5、nodejs的json时间"2018-03-04T11:14:27.878Z"
//获取时间戳对应的可读事件 Array返回数组事件 string 返回年月日处理
//得到年月日,格式为:2018-01-01
U.UF.D.getYearMonthDay = function (date) {
    if (date) {
        var _date = U.UF.D.formatDateToArray(date); //把时间格式化为数组
        var _dates = _date.slice(0, 3).join("-"); //拼凑需要的格式
        return _dates;
    }
    return "";
}

//把数据库的时间戳转换成可读时间
//参数一:时间格式  
//   1、javascrpt 自带的时间格式 datetime类型 Sun Mar 04 2018 18:45:54 GMT+0800 (中国标准时间)
//   2、sqlserver 时间格式 /Date(1364812396843)/
//   3、mongodb 时间格式 2018/01/01 01:01:01
//   4、mysql 时间格式 2018-01-01 01:01:01
//   5、nodejs的json时间"2018-03-04T11:14:27.878Z"
//获取时间戳对应的可读事件 Array返回数组事件 string 返回年月日处理
//得到年月日,格式为:2018-01-01
U.UF.D.getHoursMinutesSecond = function (date) {
    var _date = U.UF.D.formatDateToArray(date, true); //把时间格式化为数组
    var _dates = _date.slice(3, 6).join(":"); //拼凑需要的格式
    return _dates;
}


//参数一:时间格式  
//   1、javascrpt 自带的时间格式 datetime类型 Sun Mar 04 2018 18:45:54 GMT+0800 (中国标准时间)
//   2、sqlserver 时间格式 /Date(1364812396843)/
//   3、mongodb 时间格式 2018/01/01 01:01:01
//   4、mysql 时间格式 2018-01-01 01:01:01
//   5、nodejs的json时间"2018-03-04T11:14:27.878Z"
U.UF.D.getFullTime = function (date) {
    var _date = U.UF.D.formatDateToArray(date, true); //把时间格式化为数组
    var _dates = _date.slice(0, 3).join("-") + " " + _date.slice(3, 6).join(":"); //拼凑需要的格式
    return _dates;
}

//
//判断现在时间和从前时间的间隔,精确到分钟,小时,天数.超过3天则返回 月日时分 超过1年则返回 年月日时分
//参数一:时间格式  
//   1、javascrpt 自带的时间格式 datetime类型 Sun Mar 04 2018 18:45:54 GMT+0800 (中国标准时间)
//   2、sqlserver 时间格式 /Date(1364812396843)/
//   3、mongodb 时间格式 2018/01/01 01:01:01
//   4、mysql 时间格式 2018-01-01 01:01:01
//   5、nodejs的json时间"2018-03-04T11:14:27.878Z"
//  让学生重写
U.UF.D.getDateInterval = function (date) {
    var _return,                                                                  //申明变量
        _nowTime = U.UF.D.formatDateToArray(new Date(), "Array"),                          //申明变量_nowTime 并赋值
        _pastTime = U.UF.D.formatDateToArray(date, "Array");                                  //申明变量_pastTime 并赋值
    if (_nowTime[0] == _pastTime[0]) {                                                       //当年份为同一年时候
        if (_nowTime[2] - _pastTime[2] < 3 && _nowTime[1] == _pastTime[1]) {                                                  //判断是否是三天内发的
            if (_nowTime[2] == _pastTime[2]) {                                               //判断是否是同一天的
                if (_nowTime[3] == _pastTime[3]) {                                           //判断是否是同一小时的
                    _return = _nowTime[4] - _pastTime[4] + '分钟前';                           //是同一小时的 就给_return赋值
                } else {
                    _return = _nowTime[3] - _pastTime[3] + '小时前';                           //不是同一小时的 就给_return赋值
                }
            } else {
                _return = _nowTime[2] - _pastTime[2] + '天前';                                //不是同一天时的 就给_return赋值
            }
        } else {
            _return = _pastTime[1] + '-' + _pastTime[2] + ' ' + _pastTime[3] + ':' + _pastTime[4] + '';        //不是三天之内的 就给_return赋值
        }
    } else {
        _return = _pastTime[0] + '-' + _pastTime[1] + '-' + _pastTime[2] + ' ' + _pastTime[3] + ':' + _pastTime[4] + ''; //不是同一小年的 就给_return赋值
    }
    return _return;
}



//可读时间转化成标准时间类或者时间戳sqlserver 时间格式 /Date(1364812396843)/
//U.UF.D.toTimeStamp(UWE.birth_year + "-" + UWE.birth_month + "-" + UWE.birth_day, "-")
//把javascript时间统一为sqlserver的时间,即时间戳。
//第二个参数不要.Time stamp
U.UF.D.toTimeStamp = function (uod) {
    var _timestamp;
    if (U.UF.C.isString(uod)) {
        _timestamp = Date.parse(uod);           //如果不需要 转换获取时间戳
    }
    else if (Array.isArray(uod)) {                       //判断参数一是不是数组
        _timestamp = Date.UTC(uod[0], uod[1] - 1 || 1, uod[2] || 1, uod[3] - 8 || 1, uod[4] || 1, uod[5] || 1);
    }                                                   //转换获取时间戳
    else if (U.UF.D.isDate(uod) || !uod) {                //判断参数一是不是 日期 类型
        _timestamp = Date.parse(uod || new Date());     //转换获取时间戳
    }
    return "/Date(" + _timestamp + ")/";
}

//获取指定年月的天数,如果为2018年2月,则返回28天。
//参数一:
//   1、javascrpt 自带的时间格式 datetime类型 Sun Mar 04 2018 18:45:54 GMT+0800 (中国标准时间)
//   2、sqlserver 时间格式 /Date(1364812396843)/
//   3、mongodb 时间格式 2018/01/01 01:01:01
//   4、mysql 时间格式 2018-01-01 01:01:01
//   5、nodejs的json时间"2018-03-04T11:14:27.878Z"
U.UF.D.getDayOfMonth = function (date) {
    var _arrDate = U.UF.D.formatDateToArray(date); //把时间转换成数组形式
    var _date = new Date(_arrDate[0], _arrDate[1], 0);  //根据年月生成js时间格式
    return _date.getDate(); //返回年月对应的日
}

//比较两个时间的大小,2015-10-10  > 2014-10-10  ..文件夹或者文件从数据库取出来后是升序,现在前端做降序,则会调用冒泡排序。这里是冒泡排序比较时间
//参数一:时间
//参数二:时间
//返回字符串,"true"或者"false",如果时间一大于时间二,则为true,否则为false.相等返回euqal
//SizeComparison
U.UF.D.sizeComparison = function (date, date1) {
    var _date = U.UF.D.formatDateToArray(date),              //把时间处理成数组    并赋值
        _date1 = U.UF.D.formatDateToArray(date1);
    for (var _i = 0; _i < _date.length; _i++) {      //循环时间
        if (_date[_i] > _date1[_i]) return true;          //判断数组中每一个元素的大小
        if (_date1[_i] > _date[_i]) return false;          //date 大就返回true date1 大就返回 false
    }
    return 'equal';                                 //如果一模一样 返回'equal'
}

//Lowercase to uppercase
//小写时间转大写时间
U.UF.D.lowerToUpper = function (date) {
    var _i, _j,
        _dateArr = "",
        _dateWord = "",
        _word = [["零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"],
            ["", "十", "百", "千", "万", "亿", "兆"],
            ["年", "月", "日", "点", "分", "秒"]];
    !date ? date = new Date() : '';                                                                      //默认为当前时间
    date = U.UF.D.formatDateToArray(date);                                                                   //把时间转换成数组
    for (_i = 0; _i < date.length; _i++) {                                                            //遍历数组
        _dateArr = String(date[_i]);                                                                      //转换为字符串
        if (_i == 1) {                                                                               //当处理到年时
            for (_j = 0; _j < _dateArr.length; _j++) {                                                   //遍历字符串
                _dateWord += _word[0][_dateArr[_j]];                                                           //循环按照顺序大写
            }                                                                                       //写进_dateWord
        } else {                                                                                     //当处理其他时候
            if (Number(_dateArr) > 10) {                                                                   //判断时间是否大于十
                _dateWord += _word[0][_dateArr[0]] + _word[0][10] + (_dateArr[1] == '0' ? '' : _word[0][_dateArr[1]]); //大于十就在两个之间插个大写十
            } else {
                _dateWord += _word[0][_dateArr[0]];                                                           //就变大写
            }
        }
        _dateWord += _word[2][_i];                                                                          //加上单位('年')之类
    }
    return _dateWord;
}

//#endregion 


/**
* 判断是否为时间
*
* @param  {Date} 时间对象值
* @return  {boolean} 是否为Date
*/
U.UF.D.isDate = function (date) {
    return U.UF.C.isObject(date) && U.UF.C.objectToString(date) == "[object Date]";
}


;
///<jscompress sourcefile="DynamicLoad.js" />
/*预加载处理区域*/
Namespace.register("U.UF.DL");

//#region 加载js css等

/*
* @param  {object} 对象。
如果直接加载javascript,则构建一个javascript的对象,形如{src:"http://www.1473.cn/uform.js","charset": "utf-8", "type": "text/javascript"},也可以带自定义属性。
由于QQ,微博,微信的加载方式如下:均采用对象形式构建javascript链接文件
异步加载qq登录的js  {"data-appid": "100584402", "charset": "utf-8", "src": "http://qzonestyle.gtimg.cn/qzone/openapi/qc-1.0.1.js" }
异步加载微博登录的js {"charset": "utf-8", "src": "http://tjs.sjs.sinajs.cn/open/api/js/wb.js?appkey=1242324937&i=" + Guid.newGuid(), "charset": "utf-8", "type": "text/javascript"}
异步加载微信登录js {"charset": "utf-8", "src": "http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js", "charset": "utf-8", "type": "text/javascript" }
* @param  {function} 回调函数
*/
U.UF.DL.asynLoadJs = function (obj, fun) {
    var _head = U.selectEl("head"); //获取head元素
    //创建元素
    var _script = $$("script", obj);
    //给元素设置事件
    U.UF.DL.fileElementLoaded(_script, fun);
    //追加元素
    _head.append(_script, 0, _head[0].firstChild);
    return _script;
}

/**
* 动态添加css文件
* @param  {object} 获取的地址对象 例如:{ "href": http://www.1473.cn/uform.css", "type": "text/css", "rel": "stylesheet" }。
* @param  {function} 回调函数
*返回值出去做什么?示例在哪里? 操作人可以删除这个link
*/
U.UF.DL.asynLoadCss = function (obj, fun) {
    var _head = U.selectEl("head"); //获取head元素
    //创建元素
    var _link = $$("link", obj);
    //给元素设置事件
    U.UF.DL.fileElementLoaded(_link, fun);
    //追加元素
    _head.append(_link, 0, _head[0].firstChild);
    return _link;
}

/**
* 设置异步加载文件或者iframe
* @param  {element} 加载的元素
----------$("iframe", { "id": _UTP, "name": _UTP, "width": 0, "height": 0, "style": { "display": "none" }, "src": _UDE[i][1] }, _UCS)的iframe对象。
* @param  {function} 回调函数
*/
U.UF.DL.iframeLoad = function (obj, fun) {
    U.UF.DL.fileElementLoaded(obj, fun);
}

//iframe,script标签,link标签三种元素的加载事件设置,并且回调
/**
* @param  {element} 加载的元素
----------$("iframe", { "id": _UTP, "name": _UTP, "width": 0, "height": 0, "style": { "display": "none" }, "src": _UDE[i][1] }, _UCS)的iframe对象。
* @param  {function} 回调函数
_B布尔类型
*/
U.UF.DL.fileElementLoaded = function (obj, fun) {
    //ie系列的处理
    if (obj.onreadystatechange !== undefined) {
        //为obj添加事件处理函数 类似于onclick之类的
        obj.onreadystatechange = function () {
            //成功加载的状态码的判断。 在ie系列下readyState == complete 的时候为加载成功
            if (obj.readyState == "complete") {
                //加载成功后去除事件
                obj.onreadystatechange = null;
                //没加载成功重新执行isFunction函数
                if (U.UF.C.isFunction(fun)) {
                    //等加载成功直接回调
                    fun.call(obj)
                }
            }
        }
    }
    //如果是非ie浏览器支持onload事件加载iframe、 js 、css
    else {
        //为obj添加事件处理函数 类似于onclick之类的
        obj.onload = function () {
            //加载成功后去除事件
            obj.onload = null;
            //没加载成功重新执行isFunction函数
            if (U.UF.C.isFunction(fun)) {
                //等加载成功直接回调
                fun.call(obj)
            }
        }
    }
}

/**
* 在head头部追加样式styleText
*
* @param  {string} style标签的内容
* 例:U.UF.DL.loadStyle=(".classname  {width:100px}")
*返回值:object 返回出去做什么?用途在哪里? 用户可以根据自己的需求去管理这个object 例如当用户已经加载好不需要这个style可以删除这个style
*/

U.UF.DL.loadStyle = function (csstext) {
    //Style
    var _head = U.selectEl("head")[0]; //获取head标签
    var _style = $$("style", {}); //创建一个style标签 
    //如果HTML5有此属性,则直接写内容
    if (_style.styleSheet) { //html5兼容
        _style.styleSheet.cssText = csstext;
    }
    else { //ie兼容
        //否则,直接追加孩子节点.
        _style.appendChild(document.createTextNode(csstext));
    }
    _head.appendChild(_style);
    document.body.offsetHeight; //添加设置和执行,重绘本页面.
    return _style;
}

/*
**作用:在网页开发的过程中,我们会通过Ajax去后台进行通讯交互,
*       在交互的过程中,我们无法预料整个交互的过程的时间,如果这里时候页面上没有任何的提示,
*       那么用户会认为页面上不具备该功能,导致用户体验非常不好,所以在我们调用后台请求的时候,
*       在指定的元素地方加上一个图片loading效果,那么在加载服务器数据的时候页面用户可以看到等待进行的图片,
*       这样的话大大增加了用户体验,Loding加载功能主要的作用就是能在Ajax加载页面数据的时候,
*       在指定区域的添加一张loading的图片
**案例:引用uform框架U.A.Request去后台取数据的时候,有的时候网络情况不是特别好,
*       那么可能会在后台查询有段时间,那么这个时候就会通过U.UF.DL.loading(element);
*       去创建一个loading加载等待数据
**@param {element} el 添加要加一个图片loading效果的指定的的元素
*/
U.UF.DL.loading = function (el) {
    //判断是否有需要添加loading效果的元素
    if (el) {//如果有需要添加loading效果的元素
        //判断是否添加了loading元素
        //        if (el.loadingel) {
        //            return false;
        //        }
        //        else {
        // var _elparent = U.selectEl(el).Parent(); //获取添加loading效果的指定元素的父级元素
        //            var _width = U.selectEl(_elparent)[0].style.width || U.UF.EL.getElementRealWidth ($(_elparent)[0]) + "px";//获取添加loading效果的元素的父级元素的宽
        //            var _height = U.selectEl(_elparent)[0].style.height || U.UF.EL.getElementRealHeight($(_elparent)[0]) + "px"; //获取添加loading效果的元素的父级元素的高
        //判断loading元素的样式display是否隐藏或者显示
        if (el.loadingel) {
            el.loadingel["P"]++;
        }
        else {
            if (U.UF.EL.offsetParent(el, true) != el) {
                el.postion = el.style.position;
                el.style.position = "relative";
            }
            var _lodingel = el.loadingel = $$("div", {
                "P": 0, //这个为loading元素
                "style": {
                    "width": "100%",
                    "height": "100%",
                    "left": 0,
                    "top": 0,
                    "position": "absolute",
                    "background-color": "#fff"
                }//做一个遮罩层,防止里面内容显示出来
            });
            var _loginimg = $$("div", {
                "style": {
                    "display": "block",
                    "z-index": "1000",
                    "width": "37px",
                    "height": "17px",
                    "position": "absolute"
                }
            }, _lodingel); //判断loading元素的样式display是否隐藏或者显示
            var _img = $$("img", { "src": "http://www.1473.cn/img/Loading.gif" }, _loginimg); //创建一个存放loading图片的img元素
            el.appendChild(_lodingel); //插入loading元素
            _loginimg.style.left = ($(el)[0].offsetWidth - _loginimg.offsetWidth) / 2 + 'px'; //获取需要loading元素的父级元素的宽度减去loading元素的宽度除以2 
            _loginimg.style.top = ($(el)[0].offsetHeight - _loginimg.offsetHeight) / 2 + 'px'; //获取需要loading元素的父级元素的高度减去loading元素的高度除以2 
            //_elparent.style.overflow = "hidden"; //给当前元素的父级元素添加一个样式,作为一个遮罩层
        }
        return _lodingel;
        //        }
    }
}

/*
** 作用:当页面加载完毕后,就移除loading效果
** @param {element} el 当前laoding元素的整体元素
*/
U.UF.DL.uploading = function (el) {
    if (el && el.loadingel && el.loadingel["P"]-- == 0) {
        //移除loading效果
        U.selectEl(el.loadingel).remove();
        el.style.position = el.postion;
        el.loadingel = null;
    }
}

//#endregion
;
///<jscompress sourcefile="Editor.js" />
/**
*编辑使用区域,
*格式定义:1、行元素为div
*          2、里面样式元素为span元素设置style
*          3、编辑功能点击按钮为button按钮 统一设置样式 padding: 0; background: 0 0; outline: 0; -moz-outline: 0; border: 0; display: block; cursor: pointer; margin: 0;
*/
Namespace.register("U.UF.E");

/* 初始化编辑器,让编辑器的格式符合
* 
* @param el  {element} 编辑的元素
* @param callback {function} 非必传 操作处理函数
*        操作处理函数 该函数默认第一个参数为操作记录。
*        格式形如 : { updateLine : [ 修改行ID, 修改行ID,], addLine : [添加行ID], deleteLine : [删除行ID] }
* @param content {string} 默认添加的内容
* @param stylestate {function}  非必传 光标所在行样式状态处理
*/
U.UF.E.initEditor = function (el, synergy, content, stylestate) {
    //el是编辑器加载到哪个元素下必须传的元素 第二个是编辑器触发的回调函数 第三个是编辑器需要加载的内容 第四个是编辑器内容变化的时候的回调函数
    //这个函数主要的逻辑内容是实现编辑器初始化内容,如果内容为空的时候那么初始化首行
    //编辑器需要初始化内容的时候
    if (content) {
        //先加载内容
        el.innerHTML = content;  //设置内容
        el.focus(); //编辑器编辑区域聚焦
        //判断加载的内容是否是通过1473编辑器初始化过的内容,如果是没有初始化过的内容,那么重新初始化
        if (!$("div", el)[0] || U.selectEl("div", el)[0].id.length != "37") {
            el.innerHTML = ""; //清理内容
            U.UF.E.textFormat(content, el); //重新加载内容
            U.selectEl("div", el)[0].focus(); //聚焦
        }
        //暂时先注释掉,去除外部引入的内容有包含可编辑元素,还有设置了不可编辑状态,导致文档不能流畅使用
        //        U.selectEl("textarea", el).remove(); //去除textarea
        //        U.selectEl("div", el).addAttrArray({ "contentEditable": "" }); //设置可编辑
    }
    //没有内容的初始化
    else {
        //创建行元素
        var _div = $$("div", { "id": "e" + Guid.newGuid(), "innerHTML": content || "<span><br /></span>" }, el); //创建一个编辑的div进行编辑处理
        el.focus(); //编辑器编辑区域聚焦
    }
    //上面处理内容后,下面初始化
    U.UF.E.variable(el, synergy, stylestate); //初始化全局变量
    //事件监听
    U.UF.E.key(el); //键盘监听
    //设置样式
    U.UF.E.formatBrush(el, false); //格式刷工具未启用状态 记录当前光标所在位置的文字样式
    //创建图片拉伸控件
    U.UF.E.picture.stretch(el); //加载图片拉伸控件
    //得到现在编辑器使用的行
    el.idarr = U.UF.E.key.getLineIdArr(el);
    //设计前进后退行记录
    el.editor.recordOpera = { "line": el.idarr }
    return U.UF.E.getRangeAt(); //得到光标
}

/* 初始化编辑器全局变量
* 
* @param el  {element} 编辑的元素
*/
U.UF.E.variable = function (el, synergy, stylestate) {
    var _range = U.UF.E.getRangeAt(); //得到光标
    //编辑器全局区域
    el.editor = {
        "isrecord": true,
        "idarr": [], //删除或者添加变化的数组
        //格式刷全局变量
        "brushStyle": {
            "font-family": {},
            "font-size": {},
            "font-weight": {},
            "font-style": {},
            "text-decoration": {},
            "color": {},
            "backgroundColor": {}
        },
        //外部引入的内容需要保留的对象
        "recordRangeStyle": {
            "font-family": "",
            "font-size": "",
            "font-weight": "",
            "font-style": "",
            "text-decoration": "",
            "color": "",
            "backgroundColor": ""
        },
        "styleState": stylestate, //样式状态管理回调
        "maxWidth": U.selectEl(el)[0].offsetWidth, //记录最大宽度
        "operaNotice": synergy,  //设置编辑器处理的回调函数
        "recordRange": _range, //当前使用的光标
        "recordHTML": "", //当前操作行的内容
        "recordOpera": {}, //记录行内容
        "dpi": U.UF.CI.getDPI()[0], //获取屏幕分辨率
        "log": true, //是否输出日志
        "recordsEditor": [], //操作记录数组
        "recordsEditorIndex": 0 //当前操作记录位置
    };
}

/* 粘贴的处理
*
* @param e       {event}  操作对象
* @param editor  {element}  编辑器
* @param text    {string}  需要处理的文字
*/
U.UF.E.onpaste = function (e, editor, text) {
    var _content, event = e || window.event;
    if (text != undefined) {
        _text = text;
    }
    else {
        _text = U.UF.C.pasteText();
    }
    _content = _text.SplitAngleBrackets();
    if (_content && _content.length < 2) {
        //普通文本替换的处理
        _text = "<div>" + _text.replaceAngleBrackets().replace(/\r\n/g, "</div><div>").replace(/  /g, " &nbsp;") + "</div>";
    }
    //进行br标签的正则替换  br标签做为独立行标签
    _text = _text.replace(/<(BR)[^<>]*>/ig, "</div></br><div>").replace(/&#32;/g, "&nbsp;");
    _text.trim() != "" && U.UF.E.textFormat(_text, editor); //文字格式化处理
    U.UF.EV.stopDefault(); //去除默认事件
    return _text.trim();
}

/* 粘贴的处理
* 
* @param text  {string}  需要处理的文字
* @param range {object}  光标对象
*
*/
U.UF.E.textFormat = function (text, editor) {
    var _editor = editor || this.editor;
    var _range = U.UF.E.getRangeAt(), //获取光标选取
        _div = $$("div", { "innerHTML": text, "style": { "display": "none"} }, U.selectEl("body")[0]), //内容
        _frag = U.UF.E.unifiedFormat(_div); //获取拆分的值
    U.UF.E.insertContent(_frag, _range, _editor); //调用指定位置插入内容的函数
    //获取table进行初始化
    var _table = U.selectEl('table', _editor);
    //表格处理 写在这里
    for (var i = _table.length - 1; i >= 0; i--) {
        U.UF.E.table.load(_table[i]);
    }
    U.selectEl(_div).remove(); //删除div元素
}


/* 在指定位置插入内容
* 
* @param el    {element} 插入的元素 frag临时标签
* @param range {object}  光标对象
*
*/
U.UF.E.insertContent = function (el, range, editor) {
    range = range || U.UF.E.getRangeAt(); //获取光标选取
    //html5浏览器
    if (window.getSelection) {
    //if (window.getSelection && el.textContent) {
        var _i, //循环变量
            _frag,
            _stylecsstext,
            _span,
            _child = el.childNodes, //获取插入元素的所有孩子节点
            _lastchild, //记录最后一个孩子节点变量
            _extractcontent, //记录删除选区内容
            _record,
            _focusel,
            _frag = $$("frag"), //创建frag 临时标签
            _startline = range.startContainer == editor ? editor.children[0] : U.UF.E.getLineElement(range.startContainer), //选择的行
            _endline = range.endContainer == editor ? editor.children[0] : U.UF.E.getLineElement(range.endContainer), //选择的列
            _selection = window.getSelection()//获取选区函数
        ;
        if (editor.innerHTML == "") {
            _record = { addLine: [] };
            for (_i = 0; _i < _child.length; ) {
                _record.addLine.push(_child[_i].id);
                //循环把选区内容元素插入到临时标签中
                editor.appendChild(_child[_i]);
            }
            U.UF.E.elementFocus(range, editor.children[0], true); //重新聚焦元素
            editor.editor.recordHTML = editor.children[editor.children.length - 1].outerHTML;
        }
        else {
            _record = { updateLine: [_startline.id], addLine: [] };
            //移除选取的内容
            range.deleteContents(); //移除文字
            _selection.removeAllRanges(); //移除选取
            //剪切区域移除br标签,反正br导致多次换行
            //            U.selectEl("br", _startline).remove(); //移除所有的br标签
            //            U.selectEl("br", _endline).remove(); //移除所有的br标签
            _lastchild = _endline.lastChild; //获取结束行最后一个元素
            //粘贴的第一行有内容的处理
            if (_lastchild && (_lastchild.innerHTML != undefined || _lastchild.data != undefined)) {
                _stylecsstext = (_lastchild.style || _lastchild.parentNode.style).cssText;    //首行的样式处理
                _focusel = _child[_child.length - 1].childNodes[_child[_child.length - 1].childNodes.length - 1] || _child[_child.length - 1];  //剪切后最后聚焦的元素
                //结束行是向前插入,先把结束好的文字剪切走
                try {
                    range.setEnd(_lastchild, _lastchild.innerHTML != undefined ? 1 : _lastchild.data.length); //设置光标结束的位置
                }
                catch (e) {
                    range.setEnd(_lastchild, 0); //设置光标结束的位置
                }
                _extractcontent = range.extractContents(); //记录删除选区内容
                //把最后一行选取的内容如果是文本那么转化成span标签 _extractcontent.childNodes[0].nodeType == 3  && U.UF.E.validElement(_extractcontent)
                if (_extractcontent.childNodes.length == 1) {
                    //重新创建一个新的粘贴信息
                    _frag = $$("frag");
                    _span = $$("span", { "style": { "cssText": _stylecsstext }, "innerHTML": _extractcontent.textContent }, _frag);
                    //_span.appendChild(_extractcontent);
                    _extractcontent = _frag;
                }
                //如果选取最后一行的内容是div说明是整行的处理
                if (_extractcontent.childNodes[0] && _extractcontent.childNodes[0].tagName == "DIV") {
                    //把行元素所有的元素添加到粘贴元素李
                    for (_i = 0; _i < _extractcontent.childNodes[0].childNodes.length; _i) {
                        //样式的设置
                        _extractcontent.childNodes[0].childNodes[_i].style.cssText = _extractcontent.childNodes[0].style.cssText + ";" + _extractcontent.childNodes[0].childNodes[_i].style.cssText;
                        _child[_child.length - 1].appendChild(_extractcontent.childNodes[0].childNodes[_i]);
                    }
                }
                //否则就是内容
                else {
                    _child[_child.length - 1].appendChild(_extractcontent); //将选区内容元素插入到选区最后一个节点
                }
                //第一行添加
                for (_i = 0; _i < el.childNodes[0].childNodes.length; _i) {
                    _startline.appendChild(el.childNodes[0].childNodes[_i]); //设置第一行的内容为插入元素的内容
                }
            }
            //否则其他的情况
            else if (_child[0]) {
                //设置起始行的样式为选区孩子节点的第一个元素的样式
                _startline.style.cssText += " " + U.UF.E.getRemainAttr(_child[0]);
                //设置起始行的内容为插入元素的第一个孩子节点的内容
                _startline.innerHTML = _child[0].innerHTML;
                _focusel = _startline;
            }
            //循环中间行添加处理
            for (_i = 1; _i < _child.length; ) {
                _record.addLine.push(_child[_i].id);
                //循环把选区内容元素插入到临时标签中
                _frag.appendChild(_child[_i]);
            }
            U.selectEl(_startline.parentNode).append(_frag, 0, U.selectEl(_startline).next()[0]); //添加到选择行的后面
            U.UF.E.elementFocus(range, _focusel, true); //重新聚焦元素
            var _focusline = U.UF.E.getLineElement(_focusel);
            if (_focusline != _startline) {
                editor.editor.recordRange = range;
            }
            editor.editor.recordHTML = _focusline.outerHTML;
        }
        U.UF.E.operationNotice(_record, editor);
        clearTimeout(editor.editor.interval); //取消计时更新
    }
    //低版本的ie兼容
    else {
        range.pasteHTML(el.outerHTML); //添加选取文字
    }
};

/* 元素全选聚焦
* 
* @param  range {object}  range光标对象
* @param  el     {element} 编辑的元素
*
*/
U.UF.E.elementFocus = function (range, el, islast) {
    //html5得到光标的处理
    if (window.getSelection) {
        var _selection = window.getSelection(); //选择选取的处理
        range.selectNodeContents(el); //添加选取的光标
        _selection.removeAllRanges(); //移除所有的光标
        _selection.addRange(range); //把聚焦元素的光标添加进去
        //判断光标是否放在最后面
        if (islast) {
            range.collapse(false);
        }
    }
    //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
    else {
        range.moveToElementText(el); //光标移动到指定的元素位置
        range.select(); //聚焦选择
    }
};

/* 创建贯标
* 
*
*/
U.UF.E.createRnage = function () {
    //html5得到光标的处理
    if (window.getSelection) {
        return document.createRange();
    }
    //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
    else {
        return document.body.createTextRange();
    }
}


/* 初始化光标处理,要求光标必须聚焦到编辑区域里,否则这里获取就会失败
* 
* @param  win {window} 编辑的域
* @return  {object} 光标编辑对象
*
*/
U.UF.E.getRangeAt = function (win) {
    var _selection, //选取对象
        _range //光标对象
    ;
    win = win || window; //获取创建光标的域
    //html5得到光标的处理
    if (win.getSelection) {
        _selection = win.getSelection(); //获取选取对象
        //当获取选取中有光标的处理
        if (_selection.rangeCount) {
            _range = _selection.getRangeAt(0); //返回选区的处理
        }
    }
    //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
    else {
        _selection = win.document.selection; //获取选取对象
        _range = _selection.createRange(); //光标对象
    }
    return _range; //光标的处理
};

/* 替换选区内容处理,可添加元素html代码。
* 
* @param str     {string} 需要插入的文字
* @param range   {object} range光标对象
* @param islast  {boolean} 是否聚焦到最后
* @return  {object} 光标编辑对象
*/
U.UF.E.addRange = function (str, range, islast) {
    range = range || U.UF.E.getRangeAt(); //获取光标处理
    //html5得到光标的处理
    if (window.getSelection) {
        var _selection = window.getSelection(), //获取选取对象
            _frag = range.createContextualFragment(str); //创建选取
        range.deleteContents(); //移除文字
        _selection.removeAllRanges(); //移除选取
        range.insertNode(_frag); //插入需要写入的内容
        //判断光标是否放在最后面
        if (islast) {
            range.collapse(false);
        }
        _selection.addRange(range); //把替换的文章添加到当前指定的选取中
    }
    //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
    else {
        range.select(); //选取聚焦
        range.pasteHTML(str); //添加选取文字
        //判断光标是否放在最后面
        if (islast) {
            range.collapse(false);
        }
    }
    //上面重新操作光标后,需要重新聚焦
    return U.UF.E.getRangeAt();
};

/* 在光标中获取现在聚焦的元素
* 
* @param range {object} range光标对象
*/
U.UF.E.getRangeElement = function (range) {
    //html5得到光标的处理
    if (range.commonAncestorContainer) {
        return range.commonAncestorContainer;
    }
    //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
    else {
        //正常选择元素获取元素的处理
        if (range.parentElement) {
            return range.parentElement();
        }
        //图片无法像上面的方法一样获取元素,需要通过commonParentElement获取元素
        else {
            return range.commonParentElement();
        }
    }
};

/* 重新选中指定的光标
* 
* @param  range {object} range光标对象
*/
U.UF.E.reSelectRange = function (range) {
    //html5得到光标的处理
    if (window.getSelection) {
        var _selection = window.getSelection(); //获取选取对象
        _selection.removeAllRanges(); //移除选取
        _selection.addRange(range); //光标重新聚焦处理
    }
    //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
    else {
        range.select(); //选取聚焦
    }
};

/* 设置编辑样式
* 
* @param attr {object}  给指定的光标设置样式
* @param range {object} 非必传参数 range光标对象
* */
U.UF.E.setRangeStyle = function (attr, range, editor) {
    range = range || U.UF.E.getRangeAt(); //获取光标处理
    if (range.startContainer == range.endContainer && range.startOffset == range.endOffset) {
        return true;
    }
    var _i, //循环变量定义
        _textstyle, //记录文本样式
        _isdel, //是否删除
        _start = range.startContainer, //选区起始元素
        _end = range.endContainer, //选区结束元素
        _startoffset = range.startOffset, //开始位置
        _endoffset = range.endOffset, //结束位置
        _startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
        _endline = U.UF.E.getLineElement(_end), //获取选区结束行元素
        _frag = $$("frag") //创建临时元素 用于做记录d
    ;
    editor = editor || _startline.parentNode; //编辑区域元素

    if (!editor.editor) { return; }
    var _record = U.UF.E.getUpdateLine(_startline, _endline, editor); //得到修改记录
    //判断是否选区在同一行
    if (_startline != _endline) {
        //不同行处理
        var _rangselect = range.extractContents().childNodes; //获取选区的所有元素
        //记录新选区的起始元素
        _start = _rangselect[0].childNodes[0];

        //记录文字装饰样式
        _textstyle = attr["text-decoration"] || attr["textDecoration"];

        //第一行样式设置
        U.UF.E.setStyle(attr, _rangselect[0], true);

        if (attr.cssText == "") {
            _startline.style.cssText = "";
        }

        //设置样式后的元素循环添加到第一行中
        while (_rangselect[0].childNodes[0]) {
            _startline.appendChild(_rangselect[0].childNodes[0]);
        }

        //如果存在文字装饰样式
        if (_textstyle) {
            //标记设置的样式中是否已存在 存在为1 不存在为 0
            _isdel = (attr["text-decoration"] || attr["textDecoration"] || "").indexOf(_textstyle) > -1 ? 1 : 0;
            attr["text-decoration"] = _textstyle;
        }
        //循环除第一行和最后一行的每一行的处理
        for (_i = 1; _i < _rangselect.length - 1; ) {
            //设置每一行的样式
            U.UF.E.setStyle(attr, _rangselect[_i], _isdel);
            if (_textstyle) {
                attr["text-decoration"] = _textstyle;
            }
            if (attr.cssText == "") {
                _rangselect[_i].style.cssText = "";
            }
            //追加到临时标签中
            _frag.appendChild(_rangselect[_i]);
        }
        //最后一行样式设置
        U.UF.E.setStyle(attr, _rangselect[_rangselect.length - 1], _isdel);
        //获取选区最后一行元素
        var _end = _rangselect[_rangselect.length - 1].childNodes[_rangselect[_rangselect.length - 1].childNodes.length - 1];
        //设置样式后的元素循环添加到最后一行中
        while (_rangselect[_rangselect.length - 1].childNodes[0]) {
            U.selectEl(_endline).append(_rangselect[_rangselect.length - 1].childNodes[_rangselect[_rangselect.length - 1].childNodes.length - 1], 0, _endline.firstChild);
        }
        if (attr.cssText == "") {
            _endline.style.cssText = "";
        }
        range.insertNode(_frag); //插入需要写入的内容
        U.UF.E.setRange(_start, _end || _start, 0, 1, range);  //设置选区 重新聚焦
    }
    //同行处理
    //同行且选择的父级为块级元素
    else if (_start == _end && (_start.parentNode.tagName.toLowerCase() == "span" || _start.parentNode.tagName.toLowerCase() == "a")) {
        var _parentspan = _start.parentNode; //获取起始标签的上级元素
        var _tagname = _parentspan.tagName.toLowerCase() == "a" ? "a" : "span"; //判断创建的块级元素TagName
        var _startsplitel = U.UF.E.splitText(_start, _startoffset); //将起始标签拆分成新的起始文本标签  返回剩余的标签
        var _endsplitel = U.UF.E.splitText(_startsplitel, _endoffset - _startoffset); //在剩余标签中拆分成选中和结束两块文本标签

        //如果第一个文本标签存在内容则创建新的span标签
        if (_start.data) {
            //创建新的span标签 该标签为起始span标签(选区前的span标签)
            var _span = $$(_tagname, {
                "style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
                "innerHTML": _start.data
            });
            //如果为a标签则设置href属性
            if (_tagname == "a") {
                _span.href = _parentspan.href;
            }

            //替换起始文本标签为起始span标签
            _parentspan.replaceChild(_span, _start);
        }
        //创建新的块级元素  该标签为选区的span标签
        var _rangspan = $$(_tagname, {
            "style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
            "innerHTML": _startsplitel.data
        });
        //处理样式后进行设置块级元素中
        U.selectEl(_rangspan).css(U.UF.E.setSpecialAttr(_rangspan, attr));

        //如果为a标签则设置href属性
        if (_tagname == "a") {
            _rangspan.href = _parentspan.href;
        }
        //替换选区文本标签为选区span标签
        _parentspan.replaceChild(_rangspan, _startsplitel);
        //如果结束文本标签存在内容则创建新的span标签
        if (_endsplitel.data) {
            //创建新的span标签 该标签为结束span标签(选区后的span标签)
            var _span1 = $$(_tagname, {
                "style": { "cssText": U.UF.E.getRemainAttr(_parentspan) },
                "innerHTML": _endsplitel.data
            });
            //如果为a标签则设置href属性
            if (_tagname == "a") {
                _span1.href = _parentspan.href;
            }
            //替换结束文本标签为结束span标签
            _parentspan.replaceChild(_span1, _endsplitel);
        }

        //将替换的元素追加到临时元素中
        for (i = 0; i < _parentspan.childNodes.length; ) {
            _frag.appendChild(_parentspan.childNodes[i]);
        }

        //替换原有元素为修改的元素
        _parentspan.parentNode.replaceChild(_frag, _parentspan);

        //设置选区
        U.UF.E.setRange(_rangspan, _rangspan, 0, _startsplitel.data ? 1 : 0, range);
    }
    //起始元素和结束元素相等 且本身就为块级元素的处理
    else if (_end == _start && _start.tagName && (_start.tagName.toLowerCase() == "span" || _start.tagName.toLowerCase() == "a")) {
        //记录原有的样式属性
        U.UF.E.getRemainAttr(_start);
        //处理样式后设置到起始元素中
        U.selectEl(_start).css(U.UF.E.setSpecialAttr(_start, attr));
    }
    //当行跨元素
    else {
        var _rangselect = range.extractContents(); //获取选区的所有元素
        U.UF.E.setStyle(attr, _rangselect, true); //直接调用设置样式函数 true表示为第一层
        range.insertNode(_rangselect); //将设置的元素插入到光标位置
    }
    //获取修改行的信息处理
    U.UF.E.operationNotice(_record, editor);
};

/* 设置样式
* 
* @param startline  {element}  修改样式修改行
* @param endline    {element}  修改样式结束行
*/
U.UF.E.getUpdateLine = function (startline, endline, edit) {
    var _record = { updateLine: [] }; //记录
    //循环找所有影响的行
    while (startline) {
        _record.updateLine.push(startline.id); //修改行记录
        //向下寻找
        if (startline != endline) {
            startline = startline.nextElementSibling;
        }
        else {
            startline = false;
        }
    }
    //返回修改记录
    return _record;
};

/* 设置样式
* 
* @param attr  {object}  给指定的光标设置样式
* @param el    {object}  设置样式的元素
* @param istop {boolean} 是否为第一层标记
*/
U.UF.E.setStyle = function (attr, el, istop) {
    var _nowattr, //记录当前属性 该变量的作用主要用于记录新的样式
        _nowspan, //记录当前元素的span元素
        _newspan, //记录新的span元素
        _textstyle = attr["text-decoration"] || attr["textDecoration"],
        _span = U.UF.E.getTagNameElement(el); //获取块级元素
    var _spanText = _span && _span.innerHTML; //获取行级元素的innerHTML
    //根据内容是否相等  判断是否选择整个span标签                  
    if (_span && _spanText == el.data) {
        _nowattr = U.UF.E.setSpecialAttr(_span, attr); //整理特殊样式
        U.selectEl(_span).css(_nowattr);  //设置样式
    }
    //如果设置样式的元素不为整个span标签
    else {
        var _rangselect = el.childNodes; //获取设置样式元素下的所有子级
        //循环给每一个子级添加样式
        for (var i = 0; i < _rangselect.length; i++) {
            //是第一层且为第一个元素是处理样式
            if (istop === true && !i) {
                U.UF.E.setSpecialAttr(_rangselect[i], attr); //设置最后需要设置的值
                //设置istop  设置后的功能为判断是否需要设置
                istop = (attr["text-decoration"] || attr["textDecoration"] || "").indexOf(_textstyle) > -1 ? 1 : 0;
            }
            //如果存在文字装饰属性
            if (attr["text-decoration"] || attr["textDecoration"]) {
                //需要添加样式的处理
                if (istop === 1) {
                    //如果为元素节点且存在文字装饰属性 并且不等于inherit和node
                    if (_rangselect[i].style && _rangselect[i].style["text-decoration"] && _rangselect[i].style["text-decoration"] != "inherit" && _rangselect[i].style["text-decoration"] != "none") {
                        //修改设置的属性为原有样式加当前样式
                        attr["text-decoration"] = _rangselect[i].style["text-decoration"].replace(_textstyle, "") + " " + _textstyle;
                    }
                    //否则则直接设置为当前样式
                    else {
                        attr["text-decoration"] = _textstyle;
                    }
                }
                //需要删除的处理
                else if (istop === 0) {
                    //判断是否为元素节点
                    //如果是元素节点
                    if (_rangselect[i].style) {
                        //判断是否存在当前样式
                        //如果存在则去除当前样式
                        if (_rangselect[i].style["text-decoration"].indexOf(_textstyle) > -1) {
                            //去除当前样式
                            attr["text-decoration"] = _rangselect[i].style["text-decoration"].replace(_textstyle, "");
                            //去除完毕后如果为空则设置为inherit
                            if (attr["text-decoration"] == "") {
                                attr["text-decoration"] = "inherit";
                            }
                        }
                        //不存在时直接替换
                        else {
                            attr["text-decoration"] = _rangselect[i].style["text-decoration"];
                        }
                    }
                    //否则直接设置为inherit(继承父级属性)
                    else {
                        attr["text-decoration"] = "inherit";
                    }
                }
            }

            //根据是否存在tagName(标签名) 判断是否为元素节点
            //如果为元素节点则直接设置样式
            if (_rangselect[i].tagName) {
                U.selectEl(_rangselect[i]).css(attr); //设置样式
            }

            //否则则创建新的span标签 并替换原有是元素
            else if (_rangselect[i].nodeValue) {
                //创建新的span标签
                _newspan = $$("span", {
                    "innerHTML": _rangselect[i].nodeValue,
                    "style": attr
                });
                //替换原有是元素
                _rangselect[i].parentNode.replaceChild(_newspan, _rangselect[i]);
            }
        }
    }
};

/*  特殊样式处理
*
* @param element {element} 被继承样式的元素
* @param attr    {object}    当前的样式属性
*/
U.UF.E.setSpecialAttr = function (element, attr) {
    var _key, //for in 循环的key值
        _newvalue, //新的值
        _value; //当前值
    if (element.style) {
        //循环没个样式
        for (_key in attr) {
            if (attr[_key] == "") {
                attr[_key] = "";
            }
            else {
                //判断是否为文字装饰样式属性
                if (_key == "text-decoration" || _key == "textDecoration") {
                    //获取当前元素该样式的值
                    _value = element.style[_key];
                    //获取的样式有值且不为继承属性时
                    if (_value && _value != "inherit" && _value != 'none') {
                        //删除样式中的属性
                        _newvalue = _value.replace(attr[_key], "");
                        //如果替换后为空则设置为继承
                        if (_newvalue == "") {
                            attr[_key] = "inherit";
                        }
                        //否则如果替换后的值相等则将值设置进去
                        else if (_newvalue == _value) {
                            attr[_key] = attr[_key] + " " + _value;
                        }
                        //如果不等于则设置为新的值
                        else {
                            attr[_key] = _newvalue;
                        }
                    }
                }
                //否则如果设置的样式等于原本的样式 则设置为继承属性
                else if (attr[_key] == element.style[_key] && "font-weight|fontWeight|font-style|fontStyle|".indexOf(_key) > -1) {
                    attr[_key] = "inherit";
                }
            }
        }
    }
    //返回处理好后的属性
    return attr;
};

/* 把一个text标签进行拆分
*
* @param  node {element} 元素节点
* @param  offset  {number} 拆分的位置
*/
U.UF.E.splitText = function (node, offset) {
    //如果拆分文字的位置等于总的长度,那么就在最后面添加空文本。
    if (offset == node.nodeValue.length) {
        var next = document.createTextNode('');
        U.selectEl(node.parentNode).append(next, null, node);
        return next;
    }
    var retval = node.splitText(offset);
    return retval;
};

/* 获取到行元素
* 
* @param  el {element} 选取元素
*/
U.UF.E.getLineElement = function (el) {
    var _mel = el,
        _tagname = el.tagName ? el.tagName.toLowerCase() : ""; //获取元素的标签名
    //循环得到行元素
    while (el && _tagname != "body" && (_tagname != "div" || !(el.id && el.id.length == "37"))) {
        el = el.parentNode;
        if (el) {
            _tagname = el.tagName ? el.tagName.toLowerCase() : ""; //标签名
        }
    };
    return (el && el.id) ? el : null;
};

/* 获取到块级元素
* 
* @param   {element} 选取元素
*/
U.UF.E.getTagNameElement = function (node, tagname) {
    tagname = tagname || 'span';
    while (node) {
        if (node.nodeName.toLocaleLowerCase() === tagname) {
            return node;
        } else if (node.nodeName.toLocaleLowerCase() === 'div' && !node.inline) {
            return null;
        }
        node = node.parentNode;
    }
};

/* 设置行的样式,如居中,局左,局右,设置编号等等功能
* 
* @param   {object} range光标对象
* @param   {object} 给指定的光标设置样式
*/
U.UF.E.setLineStyle = function (style, range) {
    if ($('.U_UF_E_Picture_dragDot')[0]) {//清除图片拉伸的的虚拟框
        U.selectEl('.U_UF_E_Picture_dragDot')[0].style.display = "none";
    }
    range = range || U.UF.E.getRangeAt(); //获取光标处理
    var _rangeline,
        _start = range.startContainer
    _td = U.selectEl(_start).Parent({ "tagName": "TD" }); //起始选区
    //判断居中的元素是不是td标签
    if (_td && _td.tagName == "TD") {
        _rangeline = [_td];
    }
    else {
        _rangeline = U.UF.E.getRangeLineElement(range);
    }
    var i = 0; //设置循环变量
    for (i = 0; i < _rangeline.length; i++) {  //循环设置样式
        U.selectEl(_rangeline[i]).css(style); //设置样式
    }
    U.UF.E.reSelectRange(range);
    return range; //返回选区对象
};

/* 获取选区行元素
* 
* @param range  {object} range光标对象
* */
U.UF.E.getRangeLineElement = function (range) {
    range = range || U.UF.E.getRangeAt(); //获取光标处理
    var _start = range.startContainer, //起始选区
        _end = range.endContainer, //结束选区
        _stratline = U.UF.E.getLineElement(_start), //起始选行
        _endline = U.UF.E.getLineElement(_end), //结束选行
        _nextline = U.selectEl(_stratline).next()[0], //下一行
        _rangeline = [_stratline]; //选中行记录
    if (_stratline != _endline) { //如果起始行不等于结束行则证明选择多行
        while (_nextline) { //循环记录选择的每一行
            _rangeline.push(_nextline); //添加到选择行记录中
            if (_nextline != _endline) { //如果依旧不等于结束行 则证明未获取完毕
                _nextline = U.selectEl(_nextline).next()[0]; //修改下一行变量
            } else { //直至等于为止
                _nextline = false;
            }
        }
    }
    return _rangeline;
}

/* 设置字体方向
* 
* @param direction {string}  方向 left center right
* */
U.UF.E.textAlign = function (direction) {
    U.UF.E.setLineStyle({ 'text-align': direction });
};

/* 设置光标位置
*
* @param   {element} 选区起始元素
* @param   {element} 选区结束元素
* @param   {number}  起始位置
* @param   {number}  结束位置
* @param   {number}  光标对象
*/
U.UF.E.setRange = function (startel, endel, start, end, range) {
    range = range || U.UF.E.getRangeAt(); //获取光标处理
    //html5处理光标选取的处理
    if (window.getSelection) {
        //判断光标没有聚焦到制定的元素上,就无法设置焦点,这里需要处理聚焦问题。
        if (startel == endel && range.startContainer != startel) {
            range.selectNodeContents(startel); //由于位置要还原制定span标签中     
        }
        range.setStart(startel, start); //设置光标开始的位置
        range.setEnd(endel, end); //设置光标结束的位置
    }
    //ie系列的处理,ie系列不支持win.getSelection,有自己独特的属性
    else {
        var _range1 = document.body.createTextRange(), //创建一个光标1
            _range2 = document.body.createTextRange(); //创建一个光标2
        _range1.moveToElementText(startel); //光标放在开始的地方
        _range1.moveStart("character", startel); //给光标设置
        _range2.moveToElementText(endel); //光标放在结束的地方
        _range2.moveStart("character", end); //设置光标结束区域的位置
        _range1.setEndPoint("EndToStart", _range2); //光标1和光标2接连在一起形成选取
        _range1.select(); //选择
        range = _range1;
    }
    return range;
}

/* 格式整理,只整理第一层和第二层
* 
* @param el {element} 整理的内容元素
*/
U.UF.E.unifiedFormat = function (el) {
    var _i, //循环
        _float,
        _tagname,
        _removeTagName = ['head', 'meta', 'script', 'link', 'style', 'title'], //需要移除的的标签
        _frag = $$("frag"), //创建临时记录内容标签
        _div, //行
        _child = el.childNodes; //获取子级,改子级全部为行
    //清除多余的元素
    U.UF.E.unifiedFormat.remove(el);
    //循环处理每一行
    for (_i = 0; _i < _child.length; _i++) {
        _display = _child[_i].currentStyle ? _child[_i].currentStyle.display : ""; //是否为行标签的处理
        _tagname = _child[_i].tagName ? _child[_i].tagName.toLowerCase() : ""; //标签名
        _float = _child[_i].currentStyle ? _child[_i].currentStyle.float : ""; //是否为行标签的处理
        //附件不进行过滤
        if (_child[_i].className == "U_MD_O_attachment") {
            U.selectEl(_child[_i]).appendTo(_frag);
            continue;
        }
        //行元素的处理
        if (!_div || (_display != "" && _display != "inline") && (_float != "left" || _float != "right")) {
            //所有的行标签的处理
            //创建行标签
            _div = $$("div", { "id": "e" + Guid.newGuid(), "style": { "cssText": U.UF.E.getRemainAttr(_child[_i])} }, _frag);
        }
        //调用非行元素处理函数 即不为第一层的处理
        U.UF.E.unifiedFormat.next(_child[_i], true, _div);
        if (!_div.childNodes.length && _frag.childNodes.length > 1) {
            U.selectEl(_div).remove();
        }
    }
    //返回处理后的临时元素
    return _frag;
};

/* 格式整理,过滤标签
* 
* @param el {element} 整理的内容元素
*/
U.UF.E.unifiedFormat.remove = function (el) {
    var _i, //循环
        _tagname, //标题名
        _removeTagName = ['head', 'meta', 'script', 'link', 'style', 'title'], //需要移除的的标签
        _child = el.childNodes; //获取子级,改子级全部为行
    //循环处理每一行
    for (_i = 0; _i < _child.length; _i++) {
        _tagname = _child[_i].tagName ? _child[_i].tagName.toLowerCase() : ""; //标签名
        //过去注释标签 nodeType为8 则为注释标签
        if (_child[_i].nodeType === 8 || (_child[_i].nodeType == 3 && _child[_i].data.trim() == "")) {
            _child[_i].remove();
            _i--;
            continue;
        }
        //删除过滤的标签
        if (_removeTagName.indexOf(_tagname) >= 0) {
            U.selectEl(_child[_i]).remove();
            _i--;
            continue;
        }
    }
}

/* 非第一行之后的所有内容处理
* 
* @param el {element} 处理的元素
* @param top {boolean}  是否为第二层标记 如果为第二层则所有标签直接修改为span标签  否则需要进行拆分
* @return 处理后的结果集
* */
U.UF.E.unifiedFormat.next = function (el, top, fragel) {
    var _i, _j, //循环变量
        _float,
        _display, //记录元素真实的display属性 用于判断是否为行级元素
        _tagname, //记录元素的tagName
        _nowspan, //记录当前span
        _tdchild, //用于子级
        _fraga = $$("frag"),
        _frag = fragel, //$$("frag"), //用于记录整理后的内容的临时标签
        _span, //用于记录块级整理后的内容
        _childcsstext, //用于记录获取到的自己的样式
        _child = el.childNodes, //获取处理元素子级
        _tagname = el.tagName ? el.tagName.toLowerCase() : "",
        _cssText = (top.style ? top.style.cssText : "") + ";" + fragel.style.cssText + (_tagname == "img" ? "" : U.UF.E.getRemainAttr(el)); //获取处理元素的样式 用户继承当前样式使用
    //清除多余的元素
    U.UF.E.unifiedFormat.remove(el);
    //如果存在子级的处理
    if (_child.length) {
        //循环处理每一个子级
        for (_i = 0; _i < _child.length; _i++) {
            _span = null; //循环重新赋值
            //整理当前元素需继承的样式  父级样式 + 当前元素原有样式
            _childcsstext = _cssText + ";" + (_child[_i].tagName == "IMG" ? "" : U.UF.E.getRemainAttr(_child[_i]));
            _display = _child[_i].currentStyle ? _child[_i].currentStyle.display : ""; //是否为行标签的处理
            _float = _child[_i].currentStyle ? _child[_i].currentStyle.float : ""; //是否为行标签的处理
            //特殊标签添加样式
            //加粗
            if (_tagname == "b") {
                _childcsstext += ";font-weight: bold;";
            }
            //斜体
            else if (_tagname == "i") {
                _childcsstext += ";font-style: italic;";
            }
            //下划线
            else if (_tagname == "u") {
                _childcsstext += ";text-decoration: underline;";
            }
            //删除线
            else if (_tagname == "s") {
                _childcsstext += ";text-decoration: line-through;";
            }

            //如果是附件的处理
            if (el.className == "U_MD_O_attachment_wrapper") {

            }
            //如果当前标签为a标签或者top为字符串(当top为字符串时表明存在href属性需要替换为a标签)
            else if (_tagname == "a" || (U.UF.C.isElement(top) && top.tagName == "A")) {
                //重新设置top值
                //    top = U.UF.C.isString(top) ? top : el.href;
                //设置name属性 用于传递使用
                _child[_i].name = _child[_i].name || top.name || el.name || "";
                //设置href属性 用于传递使用
                _child[_i].href = _child[_i].href || top.href || el.href;
                //创建a标签 并设置属性
                _span = $$("a", {
                    "name": _child[_i].name,
                    "href": _child[_i].href || "javascript:void(0)",
                    "style": { "cssText": _childcsstext }
                }, _fraga);
            }
            //style样式标签处理
            else if (_tagname == "style") {
                el = U.selectEl(el).clone(true); //克隆style标签
                el.appendTo(_frag); //天机到临时记录标签中
                //创建新的行
                arguments[2] = _frag = fragel = $$("div", {
                    "id": "e" + Guid.newGuid(),
                    "style": { "cssText": _childcsstext }
                }, fragel.parentNode);
                break; //终止整个循环
            }
            //table表格标签处理 表格固定为行标签
            else if (_tagname == "table") {
                if (_frag.innerHTML) {
                    //创建新的行标签
                    _span = $$("div", {
                        "id": "e" + Guid.newGuid(),
                        "style": { "cssText": _childcsstext }
                    }, fragel.parentNode);
                }
                else {
                    _span = _frag;
                }
                //克隆当前表格元素
                el = U.selectEl(el).clone(true);
                //将表格添加到行中
                el.appendTo(_span);
                //获取所有td节点
                _tdchild = U.selectEl("td", el[0]);
                //循环保存td节点的内容 过滤表格内的样式
                for (_j = 0; _j < _tdchild.length; _j++) {
                    _tdchild[_j].innerHTML = _tdchild[_j].innerText;
                }
                //创建新的行
                arguments[2] = _frag = fragel = $$("div", {
                    "id": "e" + Guid.newGuid(),
                    "style": { "cssText": _childcsstext }
                }, fragel.parentNode);
                break; //终止整个循环
            }
            //行元素的处理
            else if ((_display != "" && _display != "inline") && (_float != "left" || _float != "right") && _child[_i].innerHTML.trim() != "") {
                if (_frag.innerHTML) {
                    //创建新的行
                    arguments[2] = _frag = fragel = $$("div", {
                        "id": "e" + Guid.newGuid(),
                        "style": { "cssText": _childcsstext }
                    }, fragel.parentNode);
                }
                else {
                    fragel.style.cssText += _childcsstext;
                }
            }
            //否则则为块级元素
            else {
                _span = $$("span", { "style": { "cssText": _childcsstext} }, _fraga);
            }
            //进入判断是否依然存在子级 直到处理所有元素为止
            var _nowspan = U.UF.E.unifiedFormat.next(_child[_i], _span || top, fragel);
            //如果span元素的处理,说明下面只有文本元素的处理
            if (_span) {
                if (_nowspan.children.length) {
                    //替换记录标签中的块级标签元素
                    _fraga.replaceChild(_nowspan, _span);
                    _frag.appendChild(_fraga);
                }
                //如果有下级元素的处理
                else if (_nowspan.childNodes.length) {
                    _span.appendChild(_nowspan);
                    _frag.appendChild(_fraga);
                }
                else {
                    U.selectEl(_span).remove();
                }
            }
            else if (_nowspan) {
                //替换记录标签中的块级标签元素
                _fraga.appendChild(_nowspan);
                _frag.appendChild(_fraga);
            }
        }
    }
    //如果不存在子级的处理
    else {
        //是否为第二层标记
        if (top == true) {
            if (_tagname == "img") {
                var _img = U.selectEl(el).clone(true)[0];
                _img.style.maxWidth = "100%";
                _img.onerror = function () {
                    this.src = "http://www.1473.cn/img/editorError.png";
                    this.width = 150;
                    this.height = 112;
                }
                _span = $$("span", {
                    "style": { "cssText": top.style.cssText }, //继承处理元素的样式
                    //判断是否为a标签如果是则将a标签直接记录 不是则获取内容 !!!!!!!!!注释有问题
                    "innerHTML": el.innerHTML != null ? el.innerHTML : el.data
                });
                _span.appendChild(_img);
                _frag.appendChild(_span);
            }
            else {
                //如果是则直接创建span块级标签,并添加到记录标签中
                $$("span", {
                    "style": { "cssText": _cssText }, //继承处理元素的样式
                    //判断是否为a标签如果是则将a标签直接记录 不是则获取内容
                    "innerHTML": el.innerHTML != null ? el.innerHTML : el.data
                }, _frag);
            }
        }
        //如果不为第二层标记
        else {
            //且存在内容则直接创建文本节点,并添加到记录标签中
            if (el.data) {
                _fraga.appendChild(document.createTextNode(el.data));
            }
            //否则则直接克隆该元素,并添加到记录标签中 不做处理  该情况出现在img标签
            else if (_tagname == "img") {
                var _img = U.selectEl(el).clone(true)[0];
                _img.style.maxWidth = "100%";
                _img.onerror = function () {
                    this.src = "http://www.1473.cn/img/editorError.png";
                    this.width = 150;
                    this.height = 112;
                }
                _span = $$("span", {
                    "style": { "cssText": top.style.cssText }, //继承处理元素的样式
                    //判断是否为a标签如果是则将a标签直接记录 不是则获取内容
                    "innerHTML": el.innerHTML != null ? el.innerHTML : el.data
                });
                _span.appendChild(_img);
                _fraga.appendChild(_span);
            }

        }
    }
    //返回处理后的元素集合
    return _fraga;
};


/* 获取指定的css元素 暂无使用
*
* @param ele {element} 被获取的元素
* */
U.UF.E.getRemainAttr = function (ele) {
    //如果存在不存在样式 则返回空
    if (!ele || !ele.style) {
        return '';
    }
    //需要删除的属性
    var _removeattr = ['position', 'width', 'height', 'background-image', 'border', 'min-height', 'float', 'min-width', 'display', 'padding', 'margin']; // 
    var _i; //循环变量定义
    //循环将需要删除的属性的值设置为空
    for (_i = 0; _i < _removeattr.length; _i++) {
        //设置为空
        ele.style[_removeattr[_i]] = "";
    }
    //返回设置后的样式
    return ele.style.cssText;
};

/* 清除格式
*
* @param range {object} range光标对象
* */
U.UF.E.clearStyle = function (range) {
    range = range || U.UF.E.getRangeAt();   //获取光标
    var _start = range.startContainer, //选区起始元素
        _end = range.endContainer, //选区结束元素
        _startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
        _endline = U.UF.E.getLineElement(_end); //获取选区结束行元素
    //同行相同的样式
    if (_startline == _endline && range.toString() == _startline.innerText) {
        for (var i = 0; i < _startline.childNodes.length; i++) {
            if (_startline.childNodes[i].nodeName !== "#text") {
                _startline.childNodes[i].style.cssText = "font-family: 微软雅黑; font-weight: normal; font-size: 10.5pt; line-height: 2;";
            }
        }
    } else {
        U.UF.E.setRangeStyle({ "cssText": "" }, range); //设置清空样式
    }
    U.UF.E.reSelectRange(range);
};

/* 添加超链接
* 
* @param el    {object} a标签对象
* @param range {object} range光标对象
* */
U.UF.E.addHref = function (el, range) {
    U.selectEl("#U_UF_E_herfAlert").remove();
    range = range || U.UF.E.getRangeAt();  //获取光标
    var _start = range.startContainer, //获取选区起始元素
        _end = range.endContainer, //获取选区结束元素
        _selectel = range.cloneContents(), //获取选区的所有元素
        _startline = U.UF.E.getLineElement(_start), //获取选区起始行元素
        _endline = U.UF.E.getLineElement(_end); //获取选区结束行元素
    el = el || U.UF.E.getTagNameElement(range.startContainer, "a");
    //判断是否跨行选择
    if (_startline !== _endline || U.selectEl('img', _selectel)[0]) {
        //如果是则提示无法添加A标签
        U.UF.UI.alertClick('选择范围横跨多个段落或存在图片,因此无法编辑');
    } else {
        var _box = $$('div'); //创建Confirm最大层div
        if (el) {//判断是否有el
            _text = el.innerHTML; //获取文本
            _href = el.href; //获取超链接
            var _textinput = $$('div', { innerHTML: '<span style="margin-right:7px;">文本</span>&nbsp;<input class="U_MD_O_H_Inputactive" placeholder="输入文本" value="' + _text + '" style="width:210px;height:25px;border:1px solid rgba(169,169,169,1);border-radius:2px;text-indent: 3px;" />', "style": { "line-height": "25px", "margin": "40px 41px 17px"} }, _box); //创建文本区域
            var _hrefinput = $$('div', { innerHTML: '<span style="margin-right:7px;">链接</span>&nbsp;<input class="U_MD_O_H_Inputactive" placeholder="请输入网页链接地址" value="' + _href + '" style="width:210px;height:25px;border:1px solid rgba(169,169,169,1);border-radius:2px;text-indent: 3px;"/>', "style": { "margin": "0px 41px 27px", "line-height": "25px"} }, _box); //创建链接区域
            U.UF.UI.confirm(_box, U.UF.C.closure(U.UF.E.addHref.confirm, [range, _hrefinput, _textinput, _text, el])); //创建Confirm
        } else {
            //否则执行添加A标签操作
            _a = U.selectEl('a', _selectel)[0], //获取选区中的第一个a标签
            _href = _a ? _a.href : '', //如果存在则已第一个a标签做为href
            _text = range.toString(); //获取选区的文字
            var _textinput = $$('div', { innerHTML: '<span style="margin-right:7px;">文本</span>&nbsp;<input class="U_MD_O_H_Inputactive" placeholder="输入文本" value="' + _text + '" style="width:210px;height:25px;border:1px solid rgba(169,169,169,1);border-radius:2px;text-indent: 3px;"/>', "style": { "line-height": "25px", "margin": "40px 41px 17px"} }, _box); //创建文本区域
            var _hrefinput = $$('div', { innerHTML: '<span style="margin-right:7px;">链接</span>&nbsp;<input class="U_MD_O_H_Inputactive" placeholder="请输入网页链接地址" value="http://' + _href + '" style="width:210px;height:25px;border:1px solid rgba(169,169,169,1);border-radius:2px;text-indent: 3px;"/>', "style": { "margin": "0px 41px 27px", "line-height": "25px"} }, _box); //创建链接区域
            U.UF.UI.confirm(_box, U.UF.C.closure(U.UF.E.addHref.confirm, [range, _hrefinput, _textinput, _text])); //创建Confirm
        }
    }
};
/**
* Excel确定添加A标签
* @param _cellList 为选中的单元集合
* @param hrefinput {element} 链接区域元素
* @param textinput {element} 文本区域元素
* @param text      {string}  选区文本记录
*/
U.UF.E.addHref.excelConfirm = function (_cellList, hrefinput, textinput, text) {
    href = U.selectEl('input', hrefinput)[0].value; //获取输入的href
    if (U.UF.S.Url.test(href)) { //判断链接是否合理
        var _newtext = U.selectEl('input', textinput)[0].value; //获取当前文本
        //被修改则直接删除选区 创建a标签直接添加
        if (_cellList[0]) {
            $$('a', { href: href, innerHTML: _newtext, target: "_blank" }, _cellList[0]); //创建A标签
            _cellList[0].removeChild(_cellList[0].children[0]); //删除原来的文本,由创建的A标签代替
        } else {
            $$('a', { href: href, innerHTML: _newtext, target: "_blank" }, _cellList[0]); //创建A标签
        }
    }
    else {
        //提示链接存在有误
        U.alert('输入的链接有误,无法添加');
    }
};
/**
* 确定添加A标签
* @param range     {object}  range光标对象
* @param hrefinput {element} 链接区域元素
* @param textinput {element} 文本区域元素
* @param text      {string}  选区文本记录
* @param el        {object}  a标签对象
*/
U.UF.E.addHref.confirm = function (range, hrefinput, textinput, text, el) {
    href = U.selectEl('input', hrefinput)[0].value; //获取输入的href
    if (new RegExp(/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/).test(href)) { //判断链接是否合理
        var _newtext = U.selectEl('input', textinput)[0].value; //获取当前文本
        var _start = range.startContainer, //获取选区起始元素
            _end = range.endContainer, //获取选区起始元素
            _startspan = U.UF.E.getTagNameElement(_start, 'span'),
            _endspan = U.UF.E.getTagNameElement(_end, 'span');
        if (el) {//判断是否有el参数(修改)
            el.innerHTML = _newtext; //替换文本
            el.href = href; //替换超链接
        } else {
            var _frag = $$('frag');
            if (_newtext !== text) { //判断文本是否被修改
                //被修改则直接删除选区 创建a标签直接添加
                _frag = $$('a', { href: href, innerHTML: _newtext, target: "_blank" }); //创建A标签
            } else {
                var _selectel = range.extractContents(), //获取选区的所有元素
                    _rangselect = _selectel.childNodes; //获取选区的子级
                var _text = _rangselect.innerHTML || _rangselect.data;

                if (_newtext.trim() == "") {
                    $$('a', { href: href, innerHTML: href, style: { cssText: _startspan.style.cssText }, target: "_blank" }, _frag); //创建A标签
                } else {
                    var i, _csstext;
                    //循环处理每一个元素
                    for (i = 0; i < _rangselect.length; i++) {
                        if (_rangselect[i].nodeType == 3) {
                            _csstext = i == _rangselect.length ? U.UF.E.getTagNameElement(_startspan, 'span').style.cssText : U.UF.E.getTagNameElement(_end, 'span').style.cssText;
                            $$("a", { href: href, innerHTML: _rangselect[i].data, style: { cssText: _csstext }, target: "_blank" }, _frag);
                        } else {
                            $$("a", { href: href, innerHTML: _rangselect[i].innerHTML, style: { cssText: _rangselect[i].style.cssText }, target: "_blank" }, _frag);
                        }
                    }
                }

            }
            _frag = U.UF.E.unifiedFormat(_frag); //进行格式整理
            _frag.firstChild.firstChild.setAttribute("target", "_blank");
            if (_startspan.innerHTML == "") {
                U.selectEl(_startspan).remove();
            }
            if (_endspan.innerHTML == "") {
                U.selectEl(_startspan).remove();
            }
            U.UF.E.insertContent(_frag, range, U.selectEl('#U_MD_O_H_wordEditor')[0]); //调用指定位置插入内容的函数

        }
    }
    else {
        //提示链接存在有误
        U.alert('输入的链接有误,无法添加');
        return false;
    }
};

/* 超链接点击
*
*/
U.UF.E.addHref.click = function (e) {
    if (document.getElementById('U_UF_E_herfAlert')) {//如果有弹框则删除
        document.getElementById('U_UF_E_herfAlert').remove();
    }
    U.UF.EV.stopBubble(e);
    var parent = U.selectEl("#U_MD_O_R_Parent")[0]; //获取编辑区
    var _hyperlinkalert = $$('div', {
        id: "U_UF_E_herfAlert",
        style: {
            "min-width": "250px", "max-width": "360px", height: "34px", background: "rgba(255,255,255,1)", border: "1px solid rgba(243,243,243,1)", "box-shadow": "0px 5px 5px 0px rgba(45,45,45,0.1)",
            "border-radius": "2px", "line-height": "34px", "font-size": "12px", "font-family": "MicrosoftYaHei", "font-weight": "400", color: "rgba(48,126,209,1)", width: "fit-content",
            width: "-webkit-fit-content", width: "-moz-fit-content", position: "absolute", zIndex: "999"
        }
    }, parent); //创建超链接弹框
    var _link = $$('a', {
        innerHTML: e.target.href,
        style: {
            "overflow": "hidden", "text-overflow": "ellipsis", "white-space": "nowrap", cursor: "pointer",
            "max-width": "212px", "float": "left", "margin-left": "10px", "font-size": "14px"
        }
    }, _hyperlinkalert); //超链接按钮
    var _rightButton = $$('div', { classname: "out_2", style: { "float": "right"} }, _hyperlinkalert);
    var _unlink = $$('div', { innerHTML: "取消链接", style: { "float": "left", "margin-left": "20px", "margin-right": "10px", cursor: "pointer"} }, _rightButton); //取消链接按钮
    var _modify = $$('div', { innerHTML: "修改", style: { "float": "left", "margin-left": "10px", "margin-right": "10px", cursor: "pointer"} }, _rightButton); //修改按钮
    _link.onclick = function () {//链接的点击事件
        U.UF.EV.stopBubble(e);
        parent.blur();
        window.open(e.target.href); //打开目标路径
    }
    _unlink.onclick = function () {//取消链接的点击事件
        U.UF.EV.stopBubble(e);
        e.target.parentElement.replaceChild($$('span', { innerText: e.target.innerText }), e.target);
        _hyperlinkalert.remove(); //删除超链接弹框
        parent.blur();
    }
    _modify.onclick = function () {//修改的点击事件
        U.UF.EV.stopBubble(e);
        U.UF.E.addHref(e.target); //修改弹框
        parent.blur();
        _hyperlinkalert.remove(); //删除超链接弹框
    }
    /*_hyperlinkalert.style.left = e.target.offsetLeft + "px";
    _hyperlinkalert.style.top = e.target.offsetTop + 20 + "px"; //弹框的定位*/


    //弹框的定位
    console.log("超链接的位置", e.target.offsetLeft, e.target.offsetTop);
    console.log("光标的位置", e.clientX, e.clientY);
    console.log("滚动过的高度", U.selectEl('#U_MD_O_W_E_body')[0].offsetTop);
    var EditorScrollTop = U.selectEl('#U_MD_O_R_Parent')[0].parentNode.scrollTop; //滚动高度
    var EditorOffsetTop = U.selectEl('#U_MD_O_W_E_body')[0].offsetTop; //编辑器距窗口顶端的距离
    _hyperlinkalert.style.left = e.clientX + "px";
    _hyperlinkalert.style.top = e.clientY + EditorScrollTop - EditorOffsetTop + 12 + "px";
}

/* 在键盘输入的过程中处理
* 
* @param editor {element}  编辑器的对象
*/
U.UF.E.key = function (editor) {
    editor.editor.idarr = U.UF.E.key.getLineIdArr(editor); //初始化默认的行
    //将定义的//将定义的方法做为对象的onkeydown方法
    editor.onkeydown = function (e) {
        if (!editor.editor.recordOpera.range) {
            U.UF.E.recordRangeIndex(editor); //记录range处理
        }
        U.UF.E.key.keyDown(e, editor);
    };
    //失焦处理
    editor.onblur = function (e) {
        U.UF.E.key.blur(e, editor);
    };
    //将定义的方法做为对象的onkeyup方法
    editor.onkeyup = function (e) {
        U.UF.E.key.keyUp(e, editor);
    };
    //点击事件的处理
    editor.onmouseup = function (e) {
        U.UF.E.key.keyUp(e, editor, true);
    };
    editor.onclick = function (e) {
        setTimeout(function () {
            U.UF.E.key.click(e, editor);
        }, 0);
    };
    //点击记录
    editor.onmousedown = function (e) {
        setTimeout(function () {
            U.UF.E.recordRangeIndex(editor); //记录range处理
        }, 0);
    };
    //粘贴处理
    editor.onpaste = function (e) {
        var _text = U.UF.E.onpaste(e, editor); //获取text的处理
        //如果text有值则不粘贴图片
        if (!_text) {
            U.UF.E.pasteImage(e, editor);
        }
    };
    editor.ondragenter = U.UF.E.pasteImage.ignoreDrag;
    editor.ondragover = U.UF.E.pasteImage.ignoreDrag;
    editor.ondrop = U.UF.E.pasteImage.drop;
    //    U.selectEl(editor).bind({  });
};

/* 定义click方法
* 
* @param e      {event}   event对象
* @param editor {element} 编辑器对象
* */
U.UF.E.key.click = function (e, edit) {
    var _nowel, _range = U.UF.E.getRangeAt(), //获取处理的光标
        _startel = U.UF.E.getLineElement(_range.startContainer) //开始元素

    if (_startel != (_nowel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer))) {
        edit.editor.recordHTML = _startel.outerHTML;
    }
    edit.editor.recordRange = _range;
    U.selectEl('#U_UF_E_herfAlert').remove();

    if (e.target.tagName == "A") { //如果点击标签为A标签
        if (e.ctrlKey == true) { //Ctrl键是否按下
            window.open(e.target.href); //打开超链接
        } else {
            U.UF.E.addHref.click(e);
        }
    }
    else if (e.target.tagName == "IMG" && e.target.offsetParent.className != "U_MD_F_D") { //如果点击的元素为图片元素,且不是好友聊天状态中
        edit.imgStretch.img = e.target; //记录当前图片到拉伸对象中
        U.UF.E.picture.stretch.setPosition(edit.imgStretch, e); //定位显示拉伸区域
    } else {//其余情况
        edit.imgStretch.stretch.style.display = "none"; //影藏拉伸框
    }
}

/* 定义blur方法
* 
* @param e      {event}   event对象
* @param editor {element} 编辑器对象
* */
U.UF.E.key.blur = function (e, edit) {
    var _range = U.UF.E.getRangeAt(); //获取处理的光标
    if (_range) {
        var _startel = U.UF.E.getLineElement(_range.startContainer); //开始元素
        _oldstartel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer); //获取上一步操作所在的行
        if (_startel) {
            edit.editor.recordRange = _range; //记录光标对象
            edit.editor.recordHTML = _startel.outerHTML; //记录内容  以此判断内容是否发送变化
            edit.editor.log && console.log({ updateLine: [_startel.id] }, "在哪行失焦的");
            if (_oldstartel && _oldstartel.id != "U_MD_O_H_wordEditor" && _startel == _oldstartel && _oldstartel.outerHTML != edit.editor.recordHTML) {
                U.UF.E.operationNotice({ updateLine: [_startel.id] }, edit);
                clearTimeout(edit.editor.interval); //取消计时更新
            }
        }
    }
}

/* 定义onkey方法
* 
* @param e {event} event对象
* */
U.UF.E.key.keyDown = function (e, edit) {
    var _range = U.UF.E.getRangeAt(); //获取处理的光标
    if (!_range) { return; }
    var _el,
        _oldstartel,
        _line,
        _result,
        _startel = U.UF.E.getLineElement(_range.startContainer), //开始元素
        _endel = U.UF.E.getLineElement(_range.endContainer); //结束元素 
    var _code = e.keyCode || e.which || e.charCode; //键盘码
    if (_startel && _endel) {
        if (e.ctrlKey || e.metaKey) {
            edit.editor.recordRange = _range; //记录光标对象
            switch (_code) {
                case 90: //撤销(后退)
                    U.UF.E.key.undo(e, edit);
                    return;
                case 89: //重做(前进)
                    U.UF.E.key.redo(e, edit);
                    return;
            }
        }
        //判断光标是否存在的处理
        clearTimeout(edit.editor.interval); //继续编辑的话直接取消计时器
        //可能一直按着删除键,那么第一行给删除就添加第一行
        if (edit.childNodes.length == 0) {
            _result = U.UF.E.key.addDelLine(edit, _range); //删除最后一行后添加删除元素
            //判断选区中是否有内容,那么就会处理删除操作
            edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
            //记录关闭记录
            edit.editor.log && console.log(_result, "内容被情况默认添加行");
            //记录最新的行
            edit.editor.recordRange = _range; //记录光标对象
            edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容  以此判断内容是否发送变化
            //添加新行的处理
            U.UF.E.operationNotice(_result, edit);
            return;
        }
        //如果是删除行的处理
        if (_code == 9) {
            _range.deleteContents(); //移除文字
            var _frag = $$("frag");
            var _fragel = $$('div', { innerHTML: "      " });
            _frag.appendChild(_fragel.childNodes[0]);
            U.selectEl(_fragel).remove();
            _range.insertNode(_frag); //插入需要写入的内容
            U.UF.E.setRange(_range.endContainer, _range.endContainer, _range.endOffset, _range.endOffset, _range);  //设置选区 重新聚焦
            U.UF.EV.stopDefault(); //阻止浏览器默认行为
            return;
        }
        //回车处理
        if (_code === 13) {
            if (!U.UF.E.getTagNameElement(_range.commonAncestorContainer, 'table')) {
                _result = U.UF.E.key.addLine(_range); //调用方法,新建行
                //判断选区中是否有内容,那么就会处理删除操作
                edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
                U.UF.EV.stopDefault(); //阻止浏览器默认行为
                //记录关闭记录
                edit.editor.log && console.log(_result, "更新换行的行,添加新的行");
                //记录最新的行
                edit.editor.recordRange = _range; //记录光标对象
                edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容  以此判断内容是否发送变化
                //添加新行的处理
                U.UF.E.operationNotice(_result, edit);
            }
        }
        else {
            edit.editor.recordDownHTML = _startel.outerHTML; //记录内容  以此判断内容是否发送变化        
            if (_startel == _endel && edit.editor.recordRange.endOffset != edit.editor.recordRange.startOffset) {
                setTimeout(U.UF.C.closure(function (startel, edit) {
                    if (edit.editor.recordHTML != startel.outerHTML) {
                        var _result = { updateLine: [_startel.id] };
                        U.UF.E.operationNotice(_result, edit);
                        edit.editor.log && console.log(_result, "存在选区的输入,即时更新");
                        edit.editor.recordHTML = startel.outerHTML;
                        edit.editor.recordRange = U.UF.E.getRangeAt();
                    }
                }, [_startel, edit]), 0);
                clearTimeout(edit.editor.interval); //取消计时更新
            }
            _line = U.UF.E.key.getLineIdArr(edit); //获取
            _result = U.UF.E.diff(_line, edit.editor.idarr); //对比得到删除的值
            edit.editor.idarr = _line; //删除信息
            //换行后回调的处理
            if (_result.deleteLine.length) {
                U.UF.E.operationNotice(_result, edit);
                edit.editor.log && console.log(_result, "未松开删除按钮时,删除了行");
                if (_result.updateLine[0]) {
                    edit.editor.recordHTML = U.selectEl("#" + _result.updateLine[0])[0].outerHTML;
                    edit.editor.recordRange = _range;
                }
            }
            //没有任何特殊处理等待一点五秒的处理
            else {
                //普通的编辑那边等待记录,1.5秒后告诉用户修改信息
                edit.editor.interval = setTimeout(function () {
                    if (edit.editor.recordHTML != _startel.outerHTML) {
                        //回调处理
                        U.UF.E.operationNotice({ updateLine: [_startel.id] }, edit);
                        edit.editor.log && console.log({ updateLine: [_startel.id] }, "超时更新行");
                        //记录当前的行
                        edit.editor.recordRange = _range; //记录光标对象
                        edit.editor.recordHTML = _startel.outerHTML; //记录内容  以此判断内容是否发送变化
                    }
                }, 1000);
            }
        }
    }
};

/* 定义键盘离开事件
* 
* @param e {event} event对象
* */
U.UF.E.key.keyUp = function (e, edit, click) {
    var _range = U.UF.E.getRangeAt(); //获取处理的光标
    var _code = e.keyCode || e.which || e.charCode; //键盘码
    if (e.ctrlKey == false) {
        U.selectEl(edit).removeClass('U_MD_O_ctrlPress');
    }
    if (_range) {
        var _line,
            _result,
            _oldstartel,
            _startel = U.UF.E.getLineElement(_range.startContainer), //开始元素
            _endel = U.UF.E.getLineElement(_range.startContainer); //结束元素

        //判断第一层是否被删除掉,如果不是
        if (edit.childNodes.length == 0) {
            _result = U.UF.E.key.addDelLine(edit, _range); //删除最后一行后添加删除元素
            //判断选区中是否有内容,那么就会处理删除操作
            edit.editor.idarr = U.UF.E.key.getLineIdArr(edit); //获取当前文档的id集合
            //记录关闭记录
            edit.editor.log && console.log(_result, "内容被情况默认添加行");
            //记录最新的行
            edit.editor.recordRange = _range; //记录光标对象
            edit.editor.recordHTML = U.UF.E.getLineElement(_range.startContainer).outerHTML; //记录内容  以此判断内容是否发送变化
            //添加新行的处理
            U.UF.E.operationNotice(_result, edit);
            return;
        }
        _oldstartel = U.UF.E.getLineElement(edit.editor.recordRange.startContainer); //记录之前开始的行
        //开始位置切换了,那么就要把开始位置作为修改行
        if (_oldstartel && (_oldstartel != edit && _oldstartel != _startel || (_startel == _oldstartel && _startel.outerHTML != edit.editor.recordDownHTML))) {
            if (edit.editor.recordHTML != _oldstartel.outerHTML) {
                var _result = { "updateLine": [_oldstartel.id] };
                U.UF.E.operationNotice(_result, edit);
                edit.editor.log && console.log(_result, "光标切换且内容发送变化时");
                clearTimeout(edit.editor.interval); //取消计时更新
            }
            edit.editor.recordRange = _range;
            edit.editor.recordHTML = _startel.outerHTML;
        }
        if (_code > 36 && _code < 41) {
            U.UF.E.recordRangeIndex(edit); //记录range处理
        }
        _line = U.UF.E.key.getLineIdArr(edit); //获取
        _result = U.UF.E.diff(_line, edit.editor.idarr);
        edit.editor.idarr = _line;
        //删除行的处理
        if (_result.deleteLine.length) {
            U.UF.E.operationNotice(_result, edit);
            edit.editor.log && console.log(_result, "删除了行");
            var _range = U.UF.E.getRangeAt();
            edit.editor.recordRange = _range;
            edit.editor.recordHTML = U.UF.E.getLineElement(_range.commonAncestorContainer).outerHTML;
            clearTimeout(edit.editor.interval); //取消计时更新
        }
        U.UF.E.formatBrush(edit, false); //格式刷工具未启用状态 记录当前光标所在位置的文字样式
    }
};

/* 把编辑器里面的内容转换为数组,数组的id为div的id。
* 
* @param edit {element} 编辑器元素
* @return 数组
* */
U.UF.E.key.getLineIdArr = function (edit) {
    var _i,
        _arr = [];
    //循环添加子元素
    for (_i = 0; _i < edit.childNodes.length; _i++) {
        //判断是否是行元素,只有行元素才记录
        if (edit.childNodes[_i].tagName && edit.childNodes[_i].tagName.toLowerCase() === "div") {
            //记录id和innerHTML
            _arr.push({ "id": edit.childNodes[_i].id, "innerHTML": edit.childNodes[_i].outerHTML });
        }
    }
    return _arr;
};

/* 比较编辑器列删除方法
* 
* @param   arr 进行比较的数组一
* @param   arr 进行比较的数组二
*/
U.UF.E.diff = function (arr1, arr2) {
    var temp = []; //临时数组1
    var temparray = []; //临时数组2
    var _i, _j; //循环变量
    var _updateLine = [];
    for (_i = 0; _i < arr1.length; _i++) {
        temp[arr1[_i].id] = true; //把数组B的值当成临时数组1的键并赋值为真
    }
    for (_j = 0; _j < arr2.length; _j++) {
        //同时把数组A的值当成临时数组1的键并判断是否为真,如果不为真说明没重复,就合并到一个新数组里,这样就可以得到一个全新并无重复的数组
        if (!temp[arr2[_j].id]) {
            if (_updateLine.length == 0) {
                _updateLine.push(arr2[_j - 1].id);
            }
            temparray.push(arr2[_j].id);
        }
    }
    return {
        updateLine: _updateLine,
        deleteLine: temparray
    }; //返回差异值
}

/* 添加删除后的空行
* 
* @param 编辑器元素
* @param range 可选
* @returns {*} 返回id
*/
U.UF.E.key.addDelLine = function (edit, range) {
    var _range = range || U.UF.E.getRangeAt(), //获得光标的位置
        _el = $$("div", { id: edit.editor.idarr[0] ? edit.editor.idarr[0].id : "e" + Guid.newGuid(), innerHTML: "<span><br></span>" }, edit); //重新创建第一行,值为原第一行的id
    _range.selectNodeContents(_el);  //将光标重选中添加的内容
    _range.collapse(true); //向右折叠光标选区,设置结束点和开始点相同地方
    return { addLine: [_el.id] };
}

/* 添加行
* 
* @param range 可选
* @returns {*} 返回id
*/
U.UF.E.key.addLine = function (range) {
    var _txtnode, //换行后的文本内容
        _range = range || U.UF.E.getRangeAt(), //获得光标的位置
        _startline = U.UF.E.getLineElement(_range.startContainer), //得到起始行的div
        _el = $$('div', { id: "e" + Guid.newGuid(), style: { cssText: _startline.style.cssText} }), //需要添加的新元素
        _result = {} //添加行后会影响变化的值
    ;

    //删除已经选中的内容
    if (_range.startOffset != _range.endOffset && _range.startContainer.innerHTML !== "<br>") {
        _range.deleteContents();
    }

    _range.setEnd(_startline, _startline.childNodes.length); //设置光标结束点的位置
    _txt = _range.extractContents(); //剪切文本处理

    if ($("img", _txt)[0]) {
        _txtnode = _txt;
    }
    //判断选取是否有内容,若有返回内容,反之添加一个br标签占位
    else if (_txt.textContent.trim() === '') { //如果没有内容那么就添加一个br标签
        _txtnode = $$('span', { style: { cssText: (_startline.lastChild && _startline.lastChild.style) ? _startline.lastChild.style.cssText : "" }, innerHTML: "<br>" });
    }
    //设置内容
    else {
        _txtnode = _txt;
    }
    //如果回车行的内容为"",且没有存在有效元素 那么就记录原有样式创建默认行
    if (_startline.innerText == '' && !U.UF.E.validElement(_startline)) {
        var _clone = _txtnode.nodeName == "SPAN" ? _txtnode : U.selectEl('span', _txtnode)[0]; //获取可克隆样式元素
        var _content = _clone ? U.selectEl(_clone).clone()[0] : $$('span', { innerHTML: "<br>" });  //创建内容
        _content.innerHTML = "<br>"; //设置默认内容
        U.selectEl(_content).appendTo(_startline); //追加
    }
    _el.appendChild(_txtnode); //添加到创建的div里面
    U.UF.E.insertAfter(_el, _startline); //添加到选中的div下面
    _range.selectNodeContents(_el);  //将光标重选中添加的内容
    _range.collapse(true); //向右折叠光标选区,设置结束点和开始点相同地方
    _result.addLine = [_el.id]; //添加新的行
    _result.updateLine = [_startline.id]; //结束新的行
    return _result; //返回添加的id
};

/* 判断某个元素内是否存在有效元素(存在内容、存在图片等),过滤无用元素(空span)  
*
* @param el {element} 父级元素
* @returns {boole} 返回是否存在有效元素
*/
U.UF.E.validElement = function (el) {
    var i, //定义循环变量
        _children = el.children,  //获取子级
        _valid = false; //默认为没有有效元素
    for (i = 0; i < _children.length; i++) { //循环处理
        if (_children[i].nodeName == "BR") {
            continue; //BR标签默认不做处理
        }
        else if (_children[i].nodeName == "IMG" || _children[i].innerText.length > 0 || ($('img', _children[i])[0] && _children[i].innerText.length == 0)) { //存在内容、存在图片则为有效元素
            _valid = true;
        }
        else { //过滤无用标题
            U.selectEl(_children[i]).remove();
            i--;
        }
    }
    return _valid; //返回结果
}

/* 在元素之后插入
* 
* @param newEl    {element}  插入的元素
* @param targetEl {element}  插入比对位置的元素
* */
U.UF.E.insertAfter = function (newEl, targetEl) {
    //插入比对位置的元素的父级元素
    var parentEl = targetEl.parentNode;
    //如果当前元素的父级元素的最后一个元素为插入比对位置的元素
    if (parentEl.lastChild === targetEl) {
        //则使用appendChild直接添加到最后
        parentEl.appendChild(newEl);
    } else {
        //否则则采用insertBefore 添加到插入比对位置的元素的上一个元素后
        parentEl.insertBefore(newEl, targetEl.nextSibling);
    }
    //返回插入的元素
    return newEl;
};

/* 复制格式
*
* 效果:把选区内的第一个或开始位置的字体样式复制,赋值到常量里
* */
U.UF.E.formatBrush = function (el, pattern) {
    el = el || U.selectEl('#U_MD_O_H_wordEditor')[0];
    if (U.UF.E.formatBrush.callBack && U.UF.E.formatBrush.pattern) {
        U.UF.E.formatBrush.pattern = undefined;
        U.selectEl(el).bind('mouseup', U.UF.E.formatBrush.callBack);
        return;
    }
    var _style = pattern == false ? el.editor.recordRangeStyle : el.editor.brushStyle;
    var range = U.UF.E.getRangeAt();
    //获取选区
    var _start = range.startContainer;
    //选区开始位置
    if (_start.nodeName == "DIV") {
        //如果选区开始节点是div的话,代表添加过样式之类的
        if (!range.cloneContents().children[0]) { //如果光标不能存在元素
            _style = {  // 情况格式刷数据
                "font-family": "",
                "font-size": "",
                "font-weight": "",
                "font-style": "",
                "text-decoration": "",
                "color": "",
                "background-color": ""
            };
            pattern == false && (_style["text-align"] = "", _style["name"] = "");
            return;
        }
        //获取选区内的第一个块状节点,的第一个文档节点
        //_start = range.cloneContents().children[0].firstChild;
    }
    //循环常量brushstyle 刷子样式
    var _value;
    _start = _start.nodeType == 1 ? _start : _start.parentElement;
    for (var name in _style) {
        //把相应的样式名字,内容,赋值给相应的常量值
        if (name == "font-size") {
            _value = (parseFloat(_start.currentStyle[name]) * 72 / el.editor.dpi).toFixed(1) + "pt";
        } else {
            _value = _start.currentStyle[name];
        }
        _style[name] = _value;
    }
    if (pattern !== false) { //判断是否为默认记录样式处理
        U.UF.E.formatBrush.pattern = pattern;
        if (pattern !== true) {
            U.selectEl(el).unbind("mouseup", U.UF.E.formatBrush.callBack); //是否单次取消
            U.UF.E.formatBrush.callBack = function () {  //设置鼠标起开处理
                U.UF.E.fomatBrushNext(el); //设置样式
                U.UF.E.formatBrush.pattern == undefined && U.selectEl(el).unbind("mouseup", U.UF.E.formatBrush.callBack); //是否单次取消
            };
            U.selectEl(el).bind('mouseup', U.UF.E.formatBrush.callBack);
        }
    }
    else {
        _style["text-align"] = U.UF.E.getLineElement(_start).currentStyle.textAlign;
        _style["name"] = U.UF.E.getLineElement(_start).getAttribute('name');
        U.UF.C.isFunction(el.editor.styleState) && el.editor.styleState(el.editor.recordRangeStyle);
    }
};

/* 粘贴复制的样式
*
* 效果: 把常量复制到样式,粘贴到编辑器中
* */
U.UF.E.fomatBrushNext = function (el) {
    U.UF.E.setRangeStyle({ "cssText": '' });
    //在赋值相应的样式
    U.UF.E.setRangeStyle(el.editor.brushStyle);
};

/* 附件功能
* 
* @param input  {element} input文件域元素
* @param editor {element} 编辑器元素
*/
U.UF.E.attachment = function (input, editor) {
    if (input.files.length) { //判断是否存在文件
        var _range = U.UF.E.getRangeAt(); //获取光标处理
        U.UF.UP.inputUpload([input], 'http://disk.1473.cn/USUpfile.ashx?typename=UseStudioEditor&UserId=FA92AAC5-4134-449F-9659-0DC12F4F68E9', function (r) { //调用统一上传处理
            var _file, _filetype, _input = r.context[0];
            var _imgtype = /.*(jpg|png|gif|jpeg|JPG|PNG|GIF|JPEG|bmp|BMP)$/;
            var _filearray = []; //记录上传图片的数组
            if (Object.prototype.toString.call(r.value[0]) != "[object Array]") { //根据返回值类型判断是否多图上传
                _filearray = [r.value]; //单图用数组则直接记录
            } else {
                _filearray = r.value; //多图则直接替换即可
            }
            var _el, _frag = $$('frag');
            for (i = 0; i < _filearray.length; i++) { //循环评接拼接
                _file = _input.files[i];
                _filetype = _file.name.substring(_file.name.lastIndexOf('.') + 1, _file.name.length); //获取文件后缀名
                if (_filetype.match(_imgtype)) {//图片类型处理
                    _el = $$("div", {}, _frag); ;
                    $$('span', { innerHTML: ' <img src="http://fs.1473.cn/' + _filearray[i][0] + '">' }, _el);
                }
                else { //其余文件类型处理
                    _el = U.UF.E.attachment.create(_file, _filearray[i][0], _filetype);
                    U.selectEl(_el).appendTo(_frag);
                }
            }
            _frag = U.UF.E.unifiedFormat(_frag); //进行格式整理
            U.UF.E.insertContent(_frag, _range, editor || U.selectEl('#U_MD_O_H_wordEditor')[0]); //调用指定位置插入内容的函数
        }, [input]);
    }
}

/* 创建附件
* 
* @param input  {element} input文件域元素
* @param editor {element} 编辑器元素
*/
U.UF.E.attachment.create = function (file, fileinfo, type) {
    //, style: { "text-align": "center"}
    var _attachment = $$("div", { className: "U_MD_O_attachment", id: "e" + Guid.newGuid(), contenteditable: "false" }),
        _wrapper;
    var _imgtype = /.*(jpg|png|gif|jpeg|bmp)$/;

    //图片类型处理      
    if (type.match(_imgtype)) {
        $$('span', { innerHTML: ' <img src="http://fs.1473.cn/' + fileinfo[0] + '">' }, _attachment);
    } else {
        var _videotype = /.*(mp4|avi|wmv|ogg|webm|mpg|mpeg)$/;
        var _musictype = /.*(mp3|wav|mid|midi)$/;
        $$("span", { innerHTML: "&#8203;" }, _attachment);
        _wrapper = $$("span", { contenteditable: "false" }, _attachment);
        //音乐类型处理     
        if (type.match(_videotype)) {
            $$('video', { src: "http://fs.1473.cn/" + fileinfo, controls: "controls", style: { "width": "530px", "height": "300px"} }, _wrapper);
        }
        //视频类型处理     
        else if (type.match(_musictype)) {
            $$('audio', { src: "http://fs.1473.cn/" + fileinfo, controls: "controls" }, _wrapper);
        }
        //其余文件类型处理      
        else {
            _wrapper.className = "U_MD_O_attachment_wrapper";
            $$('span', { "className": "U_MD_O_attachment_wrapper_img", contenteditable: "false" }, _wrapper);
            var _info = $$("span", { className: "U_MD_O_attachment_fileinfo", contenteditable: "false" }, _wrapper);
            $$("span", { innerHTML: U.UF.E.attachment.fileNameSplice(file.name), contenteditable: "false" }, _info);
            $$("span", { innerHTML: U.UF.C.computeFileSize(file.size), contenteditable: "false" }, _info);
            $$("a", {
                "href": "http://www.1473.cn/Pages/Download.htm?id=" + fileinfo[2], //下载路径地址
                fileid: fileinfo[2], //文件id
                name: file.name, //文件名称
                type: file.name.substring(file.name.lastIndexOf('.') + 1, file.name.length), //文件后缀名
                target: "_blank",
                innerHTML: "打开",
                contenteditable: "false"
            }, _wrapper);
        }
        $$("span", { innerHTML: "&#8203;" }, _attachment);
    }
    return _attachment;

}

/* 获取附件名
* 
* @param input  {string} 文件名字
* @param editor {number} 最大长度
*/
U.UF.E.attachment.fileNameSplice = function (name, maxlength) {
    maxlength = maxlength || 30;
    var i, _index = 0, _gblen = 0, _start = "", _end = "";
    for (i = 0; i < name.length; i++) {
        if (name.charCodeAt(i) > 127 || name.charCodeAt(i) == 94) {
            _gblen += 2;
        } else {
            _gblen++;
        }
        _gblen < maxlength / 2 - 2 && (_start += name[i]);
    }
    if (_gblen > maxlength) {
        i = name.length;
        while (_index < maxlength / 2 - 2) {
            if (name.charCodeAt(i) > 127 || name.charCodeAt(i) == 94) {
                _index += 2;
            } else {
                _index++;
            }
            _end = name[name.length - _index] + _end;
            i--;
        }
        name = _start + "..." + _end;
    }
    return name;
}


/* 图片插入控件  效果:插入图片
* 
* @param input  {element} input文件域元素
* @param editor {element} 编辑器元素
*/
U.UF.E.picture = function (input, editor) {
    if (input.files.length) { //判断是否存在文件
        var _range = U.UF.E.getRangeAt(); //获取光标处理
        U.UF.UP.inputUpload([input], 'http://disk.1473.cn/USUpfile.ashx?typename=UseStudioEditor&UserId=FA92AAC5-4134-449F-9659-0DC12F4F68E9', function (r) { //调用统一上传处理
            var _input = r.context[0];
            var _imgarray = []; //记录上传图片的数组
            if (Object.prototype.toString.call(r.value[0]) != "[object Array]") { //根据返回值类型判断是否多图上传
                _imgarray = [r.value]; //单图用数组则直接记录
            } else {
                _imgarray = r.value; //多图则直接替换即可
            }
            //调用上传图片控件
            var _img = ''; //设置img元素字符串
            for (i = 0; i < _imgarray.length; i++) { //循环评接拼接
                //                $$("span", { innerHTML: "&#8203;" }, _attachment);
                _img += '<span>  <img src="http://fs.1473.cn/' + _imgarray[i][0] + '"> </span>'; //图片元素拼接
            }
            U.UF.E.textFormat(_img, editor || U.selectEl('#U_MD_O_H_wordEditor')[0]); //生成img元素
        }, [input]);
    }
}

/* word复制粘贴图片及拖拽图片函数
* 
* @param e      {event}   事件对象
* @param editor {element} 编辑器元素
*/
U.UF.E.pasteImage = function (e, editor) {
    e.preventDefault(); //阻止默认事件
    var files = e.clipboardData.files; //获取文件列表
    if (files.length && e.clipboardData.types.indexOf('Files') > -1) {
        var filebtn = $$('input', { type: "file" }) //新建文件域
        filebtn.files = files; //获取文件列表
        U.UF.E.picture(filebtn); //上传图片
        filebtn.remove(); //删除文件域
    }
    else {
        return true;
    }
}

/* 阻止拖拽默认事件
*
* @param e {event} 事件对象
*/
U.UF.E.pasteImage.ignoreDrag = function (e) {
    //因为我们在处理拖放,所以应该确保没有其他元素会取得这个事件
    e.stopPropagation();
    e.preventDefault();
}

/* 拖拽上传处理
* 
* @param e {event} 事件对象
*/
U.UF.E.pasteImage.drop = function (e) {
    //取消事件传播及默认行为
    e.stopPropagation();
    e.preventDefault();
    //取得拖进来的文件
    var data = e.dataTransfer;
    var files = data.files;
    //将其传给真正的处理文件的函数
    var filebtn = $$('input', { type: "file" })
    filebtn.files = files;
    U.UF.E.picture(filebtn, this);
    filebtn.remove();
}

/* 拉伸处理
* 
* @param el {element} 编辑器元素
*/
U.UF.E.picture.stretch = function (el) {
    var _breadth = 12;
    if (!el.imgStretch) {
        var _img = $$("div", {
            style: { display: "none", border: "1px dashed #535353", position: "absolute", minWidth: "30px", minHeight: "30px" }
        }, document.body);
        var _csstext = "width:" + _breadth + "px; height:" + _breadth + "px;position:absolute;z-index:999;background:url('http://www.1473.cn/EditorImage/yuan1.png') no-repeat";
        var _deviant = -_breadth / 2;
        //创建虚拟框
        el.imgStretch = {
            //拉伸区域
            stretch: _img,
            //左上的按钮
            nw: $$("div", { name: "nw", style: { cssText: _csstext, top: _deviant + "px", left: _deviant + "px", cursor: "nw-resize"} }, _img),
            //右上的按钮
            ne: $$("div", { name: "ne", style: { cssText: _csstext, top: _deviant + "px", right: _deviant + "px", cursor: "ne-resize"} }, _img),
            //左下的按钮
            sw: $$("div", { name: "sw", style: { cssText: _csstext, bottom: _deviant + "px", left: _deviant + "px", cursor: "sw-resize"} }, _img),
            //右下的按钮
            se: $$("div", { name: "se", style: { cssText: _csstext, bottom: _deviant + "px", right: _deviant + "px", cursor: "se-resize"} }, _img),
            //上的按钮
            n: $$("div", { name: "n", style: { cssText: _csstext, top: _deviant + "px", left: "calc(50% - " + -_deviant + "px)", cursor: "n-resize"} }, _img),
            //下的按钮
            s: $$("div", { name: "s", style: { cssText: _csstext, bottom: _deviant + "px", left: "calc(50% - " + -_deviant + "px)", cursor: "s-resize"} }, _img),
            //左的按钮
            w: $$("div", { name: "w", style: { cssText: _csstext, left: _deviant + "px", top: "calc(50% - " + -_deviant + "px)", cursor: "w-resize"} }, _img),
            //右的按钮
            e: $$("div", { name: "e", style: { cssText: _csstext, right: _deviant + "px", top: "calc(50% - " + -_deviant + "px)", cursor: "e-resize"} }, _img),
            //左边的拖动虚拟线
            l: $$("div", { name: "l", style: { position: "absolute", cursor: "e-resize", left: "-1px", width: "3px", height: "100%"} }, _img),
            //右边的拖动虚拟线
            r: $$("div", { name: "r", style: { position: "absolute", cursor: "e-resize", right: "-1px", width: "3px", height: "100%"} }, _img),
            //顶部的拖动虚拟线
            t: $$("div", { name: "t", style: { position: "absolute", cursor: "n-resize", top: "-1px", width: "100%", height: "3px"} }, _img),
            //底部的拖动虚拟线
            b: $$("div", { name: "b", style: { position: "absolute", cursor: "n-resize", bottom: "-1px", width: "100%", height: "3px"} }, _img),
            maxWidth: U.selectEl(el)[0].offsetWidth
        };
    }
    //绑定拖拽事件
    new U.UF.E.picture.stretch.bindEvent(el);
};

/* 拉伸事件绑定
* 
* @param el {element} 编辑器元素
*/
U.UF.E.picture.stretch.bindEvent = function (el) {
    this.el = el; //设置编辑器元素
    this.init(); //初始化设置
}

/* 拖拽方法
* 
*/
U.UF.E.picture.stretch.bindEvent.prototype = {
    //初始化
    init: function () {
        for (key in this.el.imgStretch) { //绑定所有可拉伸区域事件
            key !== "stretch" && key !== "maxWidth" && this.el.imgStretch[key].addEventListener('mousedown', this.mouseDown.bind(this)); //绑定事件
        }
        document.body.addEventListener('mousemove', this.mouseMove.bind(this)); //绑定事件
        document.body.addEventListener('mouseup', this.mouseUp.bind(this)); //绑定事件
    },
    //鼠标按下事件
    mouseDown: function (e) {
        this.name = e.target.name; //记录元素标识
        this.stratX = e.clientX; //起始位置X
        this.stratY = e.clientY; //起始位置Y
        this.down = true; //按下标识
    },
    //鼠标移动事件
    mouseMove: function (e) {
        if (this.down) { //如果鼠标按下
            //计算移动的坐标距离
            var _moveX = e.clientX - this.stratX;
            var _moveY = this.stratY - e.clientY;
            var _click = this.name; //获取点击名称

            //判断是否可以拉伸
            window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

            //清空移动的数据
            if (_click.length == 2 || _click == "w" || _click == "e" || _click == "l" || _click == "r") {
                //如果是右方的拖动就移动距离相反
                (_click == "w" || _click == "sw" || _click == "nw" || _click == "l") && (_moveX = -_moveX);
                //处理虚拟框的宽高,和圆圈位置
                U.UF.E.picture.stretch.moveX(this.el, this.el.imgStretch, _moveX);
            }
            if (_click.length == 2 || _click == "n" || _click == "s" || _click == "t" || _click == "b") {
                //如果是上方的拖动就移动距离相反
                (_click == "n" || _click == "nw" || _click == "ne" || _click == "t") && (_moveY = -_moveY)
                //处理虚拟框的宽高,和圆圈位置
                U.UF.E.picture.stretch.moveY(this.el.imgStretch, _moveY);
            }

            //设置新的对比起始位置
            this.stratX = e.clientX;
            this.stratY = e.clientY;
        }
    },
    //鼠标松开事件
    mouseUp: function (e) {
        if (this.down) { //如果鼠标已按下
            var _imgstretch = this.el.imgStretch; //获取拉伸元素集合
            _imgstretch.img.style.width = _imgstretch.stretch.offsetWidth + "px"; //赋值
            _imgstretch.img.style.height = _imgstretch.stretch.offsetHeight + "px"; //赋值
            U.UF.E.picture.stretch.setPosition(_imgstretch, e); //执行点击事件重新定位
            this.down = false; //设置按下标识结束
        }
    }
}

/* 设置拉伸框位置
* 
* @param obj   {object}  拉伸对象
* @param event [event}   事件对象
*/
U.UF.E.picture.stretch.setPosition = function (obj, event) {
    var _stretch = obj.stretch; //拉伸盒子元素
    var _imgel = obj.img; //被拉伸图片
    //显示虚拟框,设置虚拟框的位置,大小
    _stretch.style.display = "block";  //显示拉伸元素
    var _imgelattr = _imgel.getBoundingClientRect(); //获取位置大小属性
    if (event.clientX == event.pageX && event.clientY == event.pageY) { //当页面没有滚动时
        _stretch.style.left = _imgelattr.left + "px"; //设置值
        _stretch.style.top = _imgelattr.top + U.selectEl('body')[0].scrollTop + "px"; //设置值
    } else {
        var _offset = U.UF.E.picture.parentOfferset(_imgel, { "offsetLeft": 0, "offsetTop": 0 }); //获取父亲层的边距
        _stretch.style.left = _imgel.offsetLeft + _offset.offsetLeft + parseInt($(_imgel).css("padding-left")) + "px"; //设置值
        _stretch.style.top = _imgel.offsetTop + _offset.offsetTop + parseInt($(_imgel).css("padding-top")) + "px";  //设置值
    }
    _stretch.style.width = _imgelattr.width - 2 + "px"; //设置宽度
    _stretch.style.height = _imgelattr.height - 2 + "px"; //设置高度
    var _objattr = _stretch.getBoundingClientRect(); //获取位置大小属性
    var _breadth = obj.n.offsetWidth / 2; //计算远点大小偏移值
    obj.n.style.left = _objattr.width / 2 - _breadth + "px"; //设置顶部中心原点居中
    obj.w.style.top = _objattr.height / 2 - _breadth + "px"; //设置底部中心原点居中
    obj.s.style.left = _objattr.width / 2 - _breadth + "px"; //设置左部中心原点居中
    obj.e.style.top = _objattr.height / 2 - _breadth + "px"; //设置右部中心原点居中
}

/* 左右拖拽方法
* 
* @param el    [element} 编辑器对象
* @param obj   {object}  拉伸对象
* @param moveX [int}     移动距离
*/
U.UF.E.picture.stretch.moveX = function (el, obj, moveX) {
    var _stretch = obj.stretch; //拉伸盒子元素 
    if ((parseInt(_stretch.style.width) + moveX < obj.maxWidth && parseInt(_stretch.style.width) + moveX > 30)) { //判断拉伸后是否超出限制
        var _align = el.editor ? el.editor.recordRangeStyle["text-align"] : ""; //获取对齐方式
        switch (_align) { //判断对齐方式
            case "end": //end 为 right
            case "right": //居右处理
                _stretch.style.left = _stretch.offsetLeft - moveX + 'px'; //设置left值
                U.selectEl(_stretch)[0].style.width = parseInt(_stretch.style.width) + moveX + "px"; //设置宽度
                break;
            case "center": //居中处理
                _stretch.style.width = parseInt(_stretch.style.width) + moveX + 'px'; //设置宽度
                _stretch.style.left = parseFloat(_stretch.style.left) - moveX / 2 + 'px'; //设置偏左值
                break;
            default: //居左处理
                _stretch.style.width = parseInt(_stretch.style.width) + moveX + "px"; //设置宽度
        }
        obj.n.style.left = obj.s.style.left = _stretch.offsetWidth / 2 - obj.s.offsetWidth / 2 + "px";  //设置顶部 底部原点居中
    }
};

/* 上下拖拽方法
* 
* @param obj   {object}  拉伸对象
* @param moveX [int}     移动距离
*/
U.UF.E.picture.stretch.moveY = function (obj, moveY) {
    var _stretch = obj.stretch; //拉伸盒子元素 
    //变化虚拟框的宽度
    _stretch.style.height = _stretch.offsetHeight - 2 - moveY + "px";
    //变化左、右按钮的位置
    obj.w.style.top = obj.e.style.top = _stretch.offsetHeight / 2 - obj.w.offsetWidth / 2 + 'px';
};

/* 得到父亲层的边距
* 
* @param obj   {object}  拉伸对象
* @param moveX [int}     移动距离
* @return {object}  返回父亲层的边距
*/
U.UF.E.picture.parentOfferset = function (obj, json) {
    var _offset = {};
    //判断父亲层的左边距是否为空
    if (obj.offsetParent.offsetLeft != 0) {
        //如果有就赋值                                        
        _offset.offsetLeft = obj.offsetParent.offsetLeft;
    } else {
        //没有就赋值0
        _offset.offsetLeft = 0;
    }
    //判断父亲层的上边距是否为空
    if (obj.offsetParent.offsetTop != 0) {
        //如果有就赋值
        _offset.offsetTop = obj.offsetParent.offsetTop;
    } else {
        //没有就赋值0
        _offset.offsetTop = 0;
    }
    json.offsetLeft = _offset.offsetLeft + json.offsetLeft;
    json.offsetTop = _offset.offsetTop + json.offsetTop;
    //如果 父亲层的左边距和上边距都为0 代表,没有边距了可以返回了
    if (_offset.offsetTop == 0 && _offset.offsetLeft == 0) {
        return json;
    } else {
        return U.UF.E.picture.parentOfferset(obj.offsetParent, json);
    }
}

//#region 协同的处理

/*
* word 消息类   
* 参数一 : id 行id  
* 参数二 :  type 操作类型
* 参数三 : content 行内容
* 参数四 : next 下一行
*/
U.UF.E.editInfo = function (id, content, next) {
    var _data = {
        id: id,  //操作ID
        content: content,  //内容
        nextId: next //下一行ID
    };
    return _data;
};

/*
* 协同的处理
* @param e      {event}   event对象
* @param e      {element}   编辑器对象
*/
U.UF.E.operationNotice = function (operaRecord, editor) {
    var _opera = {}; //记录操作记录
    //是否有添加行的处理
    if (operaRecord.addLine) {
        _opera.addLine = U.UF.E.addLineMessage(operaRecord.addLine, editor); //得到操作行的协同记录
    }

    //是否有修改行的处理
    if (operaRecord.updateLine) {
        _opera.updateLine = U.UF.E.updateLineMessage(operaRecord.updateLine, editor); //得到修改行的协同记录
    }

    //是否有删除行的处理
    if (operaRecord.deleteLine) {
        _opera.deleteLine = U.UF.E.deleteLineMessage(operaRecord.deleteLine, editor); //得到删除行的协同记录
    }

    //记录前进后退
    U.UF.E.setRecord(operaRecord, editor);

    //协同回调
    if (U.UF.C.isFunction(editor.editor.operaNotice)) {
        editor.editor.operaNotice(_opera);
    }
}

/*
* 添加行
* @param      {array}   添加行的对象
* @param      {element}   编辑器对象
*/
U.UF.E.addLineMessage = function (array, edit) {
    var _i,
        _nextlineid,
        _el,
        _editinfo,
        _message = []
    ;
    //循环添加行,获取数据
    for (_i = 0; _i < array.length; _i++) {
        _el = U.selectEl('#' + array[_i])[0]; //获取添加行的元素
        _nextlineid = (_nextlineid = U.selectEl('#' + array[_i])[0].nextElementSibling) ? _nextlineid.id : null; //判断是否有下一行有返回id ,没有返回null
        _editinfo = U.UF.E.editInfo(array[_i], _el.outerHTML, _nextlineid); //初始化word信息处理
        _message.push(_editinfo);   //添加数据
    }
    return _message;
};

/*
* 修改行内容
* @param      {array}   添加行的对象
* @param      {element}   编辑器对象
*/
U.UF.E.updateLineMessage = function (array, edit) {
    var _i,
        _el,
        _editinfo,
        _message = [];

    for (_i = 0; _i < array.length; _i++) {
        _el = U.selectEl('#' + array[_i])[0]; //获取修改行的信息
        _editinfo = U.UF.E.editInfo(array[_i], _el.outerHTML, null); //初始化word信息处理
        _message.push(_editinfo);   //添加数据
    }
    return _message;
};

/*
* 删除行
* @param      {array}   删除的行
* @param      {element}   编辑器对象
*/
U.UF.E.deleteLineMessage = function (array, edit) {
    var _i,
        _editinfo,
        _message = []
    ;
    for (_i = 0; _i < array.length; _i++) {
        _editinfo = U.UF.E.editInfo(array[_i], "", null); //初始化word信息处理
        _message.push(_editinfo);   //添加数据
    }
    return _message;
};


//#endregion

//#region 前进后退方案

/*
* 添加前进后退内容(当)
* @param      {array}   添加行的对象
* @param      {element}   编辑器对象
*/
U.UF.E.setRecord = function (opera, editor) {
    if (editor.editor.isrecord && editor.editor.recordOpera && editor.editor.recordOpera.range) {
        editor.editor.recordsEditor.splice(editor.editor.recordsEditorIndex, editor.editor.recordsEditor.length - editor.editor.recordsEditorIndex);
        editor.editor.recordsEditorIndex = editor.editor.recordsEditor.length;
        //插入记录
        editor.editor.recordsEditor.push({
            "opera": opera,
            "recordLine": editor.editor.recordOpera
        });
        editor.editor.recordsEditorIndex++;
        //重新记录
        editor.editor.recordOpera = { "line": U.UF.E.key.getLineIdArr(editor) };
        U.UF.E.recordRangeIndex(editor);
    }
    editor.editor.isrecord = true;
}

/*
* 记录光标位置和内容
* @param      {array}   添加行的对象
* @param      {element}   编辑器对象
*/
U.UF.E.recordRangeIndex = function (editor) {
    //编辑器的光标处理
    var _range = U.UF.E.getRangeAt(); //得到光标
    if (_range) {
        var _startel = U.UF.E.getLineElement(_range.startContainer), //开始行
            _endel = U.UF.E.getLineElement(_range.endContainer) //结束行
        ;
        if (_startel && _endel) {
            //开始和结束行的处理
            editor.editor.recordOpera.range = {
                "startid": _startel.id,
                "endid": _endel.id,
                "endOffset": _range.endOffset, //
                "startOffset": _range.startOffset,
                "start": U.UF.E.getElementByAncestorsIndex(_startel, _range.startContainer),
                "end": U.UF.E.getElementByAncestorsIndex(_endel, _range.endContainer)
            };
        }
    }
}

/*
* 记录
* @param  {Element}   祖先元素
* @param  {Element}   子元素
*/
U.UF.E.getElementByAncestorsIndex = function (el, childel) {
    var i, j, _child, _cindex;
    //获取开始位置的处理
    if (el !== childel) {
        _child = el.childNodes;
        for (i = 0; i < _child.length; i++) {
            //聚焦到子元素下的处理
            if (_child[i] == childel) {
                _cindex = i;
                break;
            }
            //聚焦到子子元素的处理
            else if (U.UF.EL.isChild(_child[i], childel)) {
                _child = _child[i].childNodes;
                //循环子元素得到位置
                for (j = 0; j < _child.length; j++) {
                    if (_child[j] == childel) {
                        _cindex = [i, j];
                        break;
                    }
                }
            }
        }
    }
    return _cindex;
}

/* 定义撤销(后退)函数
* 
* @param e      {event}   event对象
* @param editor {element} 编辑器对象
* */
U.UF.E.key.undo = function (e, editor) {
    var i, j, k,
        _info,
        _operarecord = {},
        _index = editor.editor.recordsEditorIndex - 1,
        _record,
        _line;
    if (_index > -1 && editor.editor.recordsEditor.length >= _index) {
        _record = editor.editor.recordsEditor[_index];
        _line = _record.recordLine.line;
        //如果存在记录
        if (_record.recordLine) {
            for (i in _record.opera) {
                switch (i) {
                    //添加行的处理,如果是                                                                                                                                                                                                            
                    case "addLine":
                        //如果是后退添加行,那么直接删除
                        for (j = 0; j < _record.opera[i].length; j++) {
                            U.UF.E.deleteEditorLine(_record.opera[i][j]);
                        }
                        break;
                    case "updateLine":
                        //如果是后退添加行,那么直接删除
                        for (j = 0; j < _record.opera[i].length; j++) {
                            U.UF.E.updateEditorLine({ "id": _record.opera[i][j], "content": U.UF.E.getLineContentById(_line, _record.opera[i][j]) });
                        }
                        break;
                    case "deleteLine":
                        //如果是后退添加行,那么直接删除
                        for (j = 0; j < _record.opera[i].length; j++) {
                            _info = U.UF.E.getLineInfoById(_line, _record.opera[i][j]); //获取行信息
                            U.UF.E.addEditorLine({ "nextId": _info.next ? _info.next.id : null, "content": _info.info.innerHTML }, editor); //删除后添加回信息
                        }
                        break;
                }
            }
            U.UF.E.setRecordRange(_record.recordLine.range); //设置光标
            //如果是最后的测回,那么添加一个可前进的记录
            if (editor.editor.recordsEditor.length == _index + 1) {
                U.UF.E.setRecord(_record.opera, editor); //重新记录
            }
            editor.editor.recordsEditorIndex--;
            editor.editor.isrecord = false;
        }
    }
    //取消浏览器默认事件
    U.UF.EV.stopDefault();
}

/* 定义重做(前进)函数 
* 
* @param e      {event}   event对象
* @param editor {element} 编辑器对象
* */
U.UF.E.key.redo = function (e, editor) {
    var i, j, k,
        _info,
        _operarecord = {},
        _index = editor.editor.recordsEditorIndex,
        _record,
        _line;
    if (_index > -1 && _index < editor.editor.recordsEditor.length) {
        _record = editor.editor.recordsEditor[_index];
        _line = _record.recordLine.line;
        //如果存在记录
        if (_record.recordLine) {
            for (i in _record.opera) {
                switch (i) {
                    //添加行的处理,如果是                                                                                                                                                                                                         
                    case "addLine":
                        //如果是后退添加行,那么直接删除
                        for (j = 0; j < _record.opera[i].length; j++) {
                            _info = U.UF.E.getLineInfoById(_line, _record.opera[i][j]); //获取行信息
                            U.UF.E.addEditorLine({ "nextId": _info.next ? _info.next.id : null, "content": _info.info.innerHTML }, editor); //删除后添加回信息
                        }
                        break;
                    case "updateLine":
                        //如果是后退添加行,那么直接删除
                        for (j = 0; j < _record.opera[i].length; j++) {
                            U.UF.E.updateEditorLine({ "id": _record.opera[i][j], "content": U.UF.E.getLineContentById(_line, _record.opera[i][j]) });
                        }
                        break;
                    case "deleteLine":
                        //如果是后退添加行,那么直接删除
                        for (j = 0; j < _record.opera[i].length; j++) {
                            U.UF.E.deleteEditorLine(_record.opera[i][j]);
                        }
                        break;
                }
            }

            U.UF.E.setRecordRange(_record.recordLine.range); //设置光标
            editor.editor.isrecord = false;

            editor.editor.recordsEditorIndex++;
        }
    }
    //取消浏览器默认事件
    U.UF.EV.stopDefault();
}


/* 光标聚焦
* 
* @param e      {object}   自定义光标对象
*/
U.UF.E.setRecordRange = function (range) {
    var _startel,
        _start,
        _endel,
        _end;
    //光标开始位置和开始元素的处理
    if (range.startid && U.selectEl("#" + range.startid)[0]) {
        _start = range.startOffset; //开始位置
        //开始元素的获取
        if (range.start.length) { //如果是#text标签的处理
            _startel = U.selectEl("#" + range.startid)[0].childNodes[range.start[0]].childNodes[range.start[1]];
        }
        else { //如果是span标签的处理
            _startel = U.selectEl("#" + range.startid)[0].childNodes[range.start];
        }
    }
    //光标结束位置的处理
    if (range.endid && U.selectEl("#" + range.endid)[0]) {
        _end = range.endOffset; //结束的位置
        //结束元素的获取
        if (range.start.length) { //如果是#text标签的处理
            _endel = U.selectEl("#" + range.endid)[0].childNodes[range.end[0]].childNodes[range.end[1]];
        }
        else {//如果是span标签的处理
            _endel = U.selectEl("#" + range.endid)[0].childNodes[range.end];
        }
    }
    //选择光区聚焦
    U.UF.E.setRange(_startel, _endel, _start, _end)
}


/* 设置记录内容
* 
* @param e      {event}   event对象
* @param editor {element} 编辑器对象
*/
U.UF.E.getLineContentById = function (line, id) {
    for (var i = 0; i < line.length; i++) {
        if (line[i].id == id) {
            return line[i].innerHTML;
        }
    }
    return "";
}

/* 获取行信息
* 
* @param e      {array}   行数组
* @param editor {string} id
*/
U.UF.E.getLineInfoById = function (line, id) {
    for (var i = 0; i < line.length; i++) {
        if (line[i].id == id) {
            return { "pre": line[i - 1], "next": line[i + 1], "info": line[i] }
        }
    }
    return null;
}

/*
*  根据操作记录撤回或者前进修改信息
* @param      {object}   操作的行
*/
U.UF.E.updateEditorLine = function (opera) {
    //判断修改的元素是否存在
    if ($('#' + opera.id)[0]) {
        U.selectEl('#' + opera.id)[0].outerHTML = opera.content;
    }
    else {
        console.log('updateError', opera.id);
    }
};

/*
*  根据操作记录撤回或者前进删除信息
* @param   {object}   操作的行
*/
U.UF.E.deleteEditorLine = function (opera) {
    //删除行的处理
    U.selectEl('#' + opera.id).remove();
};

/*
* 根据操作记录撤回或者前进添加信息
* @param   {object}   操作的行
* @param   {element}  编辑器元素
*/
U.UF.E.addEditorLine = function (opera, editor) {
    editor = editor || U.selectEl('#U_MD_O_H_wordEditor')[0]; //
    var _next,
        _line = $$("div", {}, editor);
    //判断有没有nextid,nextid是否存在
    if (opera.nextId && (_next = U.selectEl('#' + opera.nextId))[0]) {
        _next.Parent().insertBefore(_line, _next[0]); //有的话插入在nexid 元素前
    }
    U.selectEl(_line)[0].outerHTML = opera.content; //替换内容
}


//#endregion
;
///<jscompress sourcefile="Element.js" />
//处理元素属性设置。HTML元素大小及定位
Namespace.register("U.UF.EL");

/*
**  作用:获取元素的定位位置
**  @param {element} el 需要获取元素的定位位置的元素
**  @return {array} arr 返回元素的位置的数组
*/
U.UF.EL.getElementPosition = function (el) {
    var _key, //获取元素的class值
        _arr = [0, 0]//获取需要返回的元素的定位位置的top和left值
    while (el && (el = el.offsetParent)) {//循环是否有el这个元素 //如果position的值为static,则获取该元素的父级元素,继续执行获取position的值,进行判断是否元素有定位位置
        _key = U.UF.EL.getStyle(el, "position"); //通过U.UF.EL.getStyle函数,获取元素的position的值
        //判断元素的position的值是什么
        if (_key != "static") {//如果position的值不为static,则执行下面内容
            _arr[0] += el.offsetTop; //获取元素的定位位置的上距
            _arr[1] += el.offsetLeft; //获取元素的定位位置的左距
        }

    }
    return _arr; //如果已经获取了元素的定位位置的上距和左距,就返回一个拥有元素定位位置的数组
}

/**
* 
*
* @param  {element} el 元素
* @param  {string} 获取长或者宽的属性
* @return {number} 返回元素宽度 
*/
U.UF.EL.getElementRealWidth = function (el) {
    var _offset; //存储元素拖动后的offset属性
    //获取元素的当前宽度,并且转化为整型
    _offset = parseInt(Math.min(el.offsetWidth, el.scrollWidth, el.clientWidth));

    //判断是否获取到了宽度属性
    if (_offset <= 0) {
        _offset = parseInt(el.style.height);    //获取元素的样式中的高度并且转化为整型
    }

    //返回元素宽度
    return _offset;
}

/**
* 
*   作用:获取元素的真实高度
*   @param  {element} 需要获取真实高度的元素
*   @param  {string} 获取长或者宽的属性
*   @return {number} 返回元素高度 
*/
U.UF.EL.getElementRealHeight = function (el) {
    var _offset; //存储元素拖动后的offset属性
    //获取元素的当前高度,并且转化为整型
    _offset = parseInt(Math.min(el.offsetHeight, el.scrollHeight, el.clientHeight));
    //判断是否获取到了高度属性
    if (_offset <= 0) {
        _offset = parseInt(el.style.height);    //获取元素的样式中的高度并且转化为整型
    }
    //返回元素高度
    return _offset;
}

/**
* 获取元素的位置大小
*
* @param  {element} el 元素
* @return  {object} 返回元素的位置  函数内有详细的注释
*/
U.UF.EL.getElementInfo = function (el) {
    var _elgetbc = el.getBoundingClientRect(), //获取
        _elp = U.UF.EL.offsetParent(el);

    //    ancestorscrollbartop
    //    ancestorscrollbarleft
    //    scrollheight
    //    scrollwidth
    //    clientheight
    //    clientwidth
    //    clienttop
    //    clientleft
    //    offsetheight
    //    offsetwidth
    //    offsetleft
    //    offsettop
    //    boundingheight
    //    boundingwidth
    //    boundingtop
    //    boundingleft
    //    boundingbottom
    //    boundingright

    return {
        ancestorscrollbartop: (document.documentElement.scrollTop) + _elp.scrollTop, //滚动条top位置
        ancestorscrollbarleft: (document.documentElement.scrollLeft) + _elp.scrollLeft, //滚动条left位置
        SH: el.scrollHeight,  //包含滚动掉的高度
        SW: el.scrollWidth, //包含滚动条的长度
        SL: el.scrollLeft, //滚动条向左的位置
        ST: el.scrollTop, //滚动条向右的位置
        CH: el.clientHeight, //页面不包含 border padding宽度
        CW: el.clientWidth, //页面不包含 border padding长度
        CT: el.clientTop, //页面margin + top的高度
        CL: el.clientLeft, //页面margin + left的长度
        OH: el.offsetHeight, ///页面包含 border padding宽度
        OW: el.offsetWidth,  //页面包含 border padding长度
        OL: el.offsetLeft, //页面left的长度 
        OT: el.offsetTop, //页面top的高度
        BCRH: _elgetbc.bottom - _elgetbc.top, //元素的显示高度
        BCRW: _elgetbc.right - _elgetbc.left, //元素的显示长度
        BCRT: _elgetbc.top, //元素的显示top
        BCRL: _elgetbc.left, //元素的显示left
        BCRB: _elgetbc.bottom, //元素的显示bottom
        BCRR: _elgetbc.right //元素的显示right
    }
}

/*
** 作用:获取元素offsetParent
** @param {element} el1 获取需要开始寻找的元素
** @param {boolean} b 是否要从上级开始找起,true为真,false为假
** @param {string} str 规定的position值
** return {element} el2 返回offsetParent
*/
U.UF.EL.offsetParent = function (el1, b, str) {
    var _str, //存放获取所需要的样式
		_el1 = document.body; //获取body部分的整体元素
    //while循环语句,之所以不用for循环,是因为for循环需要知道循环的次数,而while则用语不知道循环的次数,只要达到条件,就跳出循环
    while (el1 && el1 != _el1) {//循环条件为:是否拥有开始寻找的元素并且开始寻找的元素不超出body部分
        _str = U.UF.EL.getStyle(el1, "position"); //通过U.UF.EL.getStyle()这个函数获取元素所需要的样式
        //判断语句,判断获取的元素样式是否存在,并且样式的key值不为"static",或者是获取的元素样式是规定的position值
        if ((!str && _str != "static") || (_str == str)) {//如果满足两个条件之一
            break; //则跳出循环
        }
        el1 = el1.offsetParent; //如果不满足,则获取开始传值的元素的父级元素,继续向上一级寻找是否有需要的规定的position值
    }
    return el1; //跳出循环后,则返回offsetParent值
}


/*
**  作用:根据ID获取指定的祖先元素
**  @param {element} el 获取当前的元素
**  @param {string} str 祖先元素的id
** @return {element} 返回祖先元素
*/
U.UF.EL.getAncestor = function (el, str) {
    //循环条件,是否有当前元素,并且,当前元素的id不等于祖先元素的id
    while (el && !(el == str || el.id == str)) {//符合条件
        el = el.parentNode; //获取当前元素的父级元素,并且把当前元素的父级元素赋值为当前元素,并继续循环
    }
    return el; //如果循环出拥有id的祖先元素,则返回祖先元素
}

/*
**  作用:获取不为文字子节点的元素子节点
**  @param {element} el 当前的元素
**  @param {string} str 获取父亲元素的id
**  @return {array} 返回获取所有子节点的数组
*/
U.UF.EL.getChildrenNoText = function (el, str) {
    var i, //用于循环,获取所有子节点
        _arr = []; //用于存放获取到的子节点,并且返回
    for (i = 0; i < el.length; i++) {
        //nodeType属性返回以数字值返回指定集结点的节点类型,如果节点是元素节点,则nodeType属性将返回1
        //判断是否拥有父级元素的id,或者是检索需要的id是否存在
        if (el[i].nodeType == 1 && (!str || str.indexOf(el[i].tagName.toLowerCase()) == -1)) {//如果满足两个条件,则证明是元素子节点
            _arr.push(el[i]); //给获取子节点的数组的末尾添加获取到的元素子节点
        }
    }
    return _arr; //返回数组和数组新的长度
}

/*
**  作用:获取当前元素上级的可编辑的元素
**  @param {element} el 当前元素
*/
U.UF.EL.getAncestorEditElement = function (el) {
    var _el1 = document.body; //获取body部分的元素,不包括body以外的元素
    while (el && _el1 != el) {//while循环语句,条件为拥有当前元素,并且当前元素不超出body部分
        if (el.tagName) {//判断当前元素是否有标签名
            //判断是检索中是否当前元素是否拥有可编辑的元素,大于-1则证明有可编辑的元素 
            //或者判断元素中是否有contentEditable = true,如果有,证明也是可编辑的div元素
            if ("textarea,input".indexOf(el.tagName.toLocaleLowerCase()) > -1 || el.contentEditable == "true") {
                break; //如果符合条件,则结束循环
            }
        }
        el = U.selectEl(el).Parent(); //如果没有标签名或者是没有可编辑的元素,则获取当前元素的父级元素,继续判断
    }
    return el; //如果有可编辑的元素,则返回当前元素
}

/*
**  作用:判断元素是否是上级元素的子元素
**  @param {element} el1 该元素的父级元素
**  @param {element} el2 需要判断的元素
**  @return {boolean} b 获取元素的大小,判断是否是上级元素的子元素
*/
U.UF.EL.isChild = function (el1, el2) {
    //判断是否拥有两个传值,一个是需要判断的元素,一个是该元素的父级元素
    if (el1 && el2) {//如果有需要的元素和父级元素,则进行程序的运行
        //判断是否ie chrome兼容
        if (el1.contains) {//如果兼容
            //判断父级元素是否拥有需要判断的子元素
            if (el1.contains(el2)) {//如果父级元素有需要判断的子元素
                return true; //返回true
            }
        }
        //判断是否为Firefox的兼容
        else if (el1.compareDocumentPosition) {//如果是Firefox的兼容,compareDocumentPosition返回的是一个数值
            //判断el2位于el1的哪个位置,双!!感叹号表示把数据类型转换为bool类型
            if (!(!!(el1.compareDocumentPosition(el2)))) {//如果父级元素有需要判断的子元素
                return true; //返回true
            }
        }
    }
    return false; //返回false
}

/*
**  作用:判断元素位于指定的位置第几个
**  @param {element} el 需要判断位置的当前元素
*/
U.UF.EL.indexOfParent = function (el) {
    var _el = U.selectEl(el).Parent(); //获取当前元素的父级元素
    var _el2 = U.selectEl(_el).Child(); //获取当前元素的父级元素的所有的子元素
    return _el2.indexOf(el); //通过indexOf检索元素在指定元素的第几个位置
}

/*
**  作用:判断元素的属性是自定义属性还是系统属性,true是自定义属性,false是系统属性
**  @param {element} el 当前需要判断的元素
**  @param {string} str 判断元素的属性
**  @return {number} 位置
*/
U.UF.EL.isCustomAttributes = function (el, str) {
    el = el || $$("div"); //获取当前需要判断的元素
    var _att = el.attributes; //获取当前元素的属性集合
    //判断当前元素是否拥有属性
    if (_att) {//如果当前元素拥有属性
        //判断当前元素的属性集合是否有需要判断的元素属性,这是IE6-7的兼容
        if (_att[str]) {//如果有需要判断的元素属性
            return _att[str].expando == true; //则判断的元素属性是自定义属性
        } else {//是否为自定义属性
            //返回元素的属性的类型和值都不为空或者当前元素的指定元素为undefined
            return el.getAttribute(str) !== null || el[str] === void 0;
        }
    }
}

/*
**  作用:添加自定义属性
**  @param {array} el 获取元素
**  @param {element} name 属性的名称
**  @param {element} value 属性的值
**  实例    <div id="box" pid = "2", style="width:100px;height:100px;">
123
</div>
var box = U.selectEl("#box")[0];
box.onclick = function(){
U.UF.EL.addAttributes(box,{"pname":"pvalue","pname1":"pvalue1","pname2":"pvalue1"});//添加自定义属性
U.UF.EL.delAttributes(box,"pname");//删除自定义属性 
*/
U.UF.EL.addAttributes = function (el, name, value) {
    // 如果传入的参数为name, value 
    el.setAttribute(name, value) // 设置元素的自定义属性
}
/*
**  作用:删除自定义属性
**  @param {array} el 获取元素
**  @param {element} name 属性的名称
*/
U.UF.EL.delAttributes = function (el, name) {
    // 判断属性是否具有传入的属性名
    if (el.hasAttribute(name)) {
        el.removeAttribute(name)// 删除该属性
    }
}

/*
** 作用:获取元素所需要的样式
** @param {element} el 需要获取样式的元素
** @param {string} str 获取样式的属性值,如position:absolute,则传positon或者absolute
*/
U.UF.EL.getStyle = function (el, str) {
    //判断是否拥有需要获取样式的元素,并且,该元素有style样式
    if (el && el.style) {//如果满足两个两件,则进行下一步程序执行
        var _str = U.UF.EL.styleConversion(str); //style样式转换 如 text-align => textAlign 或者相反的换
        //判断元素是否需要的样式,并且获取的样式组为cssText
        if (el.style[_str] || _str == "cssText") {//如果同时满足两个条件
            return el.style[_str]; //返回获取需要的元素
        } else {
            //判断是否有需要的样式
            if (el.currentStyle) {//如果有
                return el.currentStyle[_str]; //返回样式值
            } else {//如果没有
                return ""; //获取js对应的的style值
            }
        }
        return ""; //获取js对应的的style值
    }
}
/*
**作用:用于指定的元素进行删除指定的class,如果class存在,那么class就删除,如果class不存则不处理
**参数一:el进行操作的对象
**参数二:str获取className的字符
*/
U.UF.EL.addClass = function (el, str) {
    var _Reg = el.className.match(new RegExp("(\\s|^)" + str + "(\\s|$)")); // ( \\s|^ ) 判断前面是否有空格 (\\s | $ )判断后面是否有空格
    var _b = !!(_Reg);  //两个感叹号为转换为布尔值 以方便做判断
    if (!_b) {//判断元素存在指定的class
        el.className += " " + str; //给指定的元素添加指定的class
    }
}

/*
**作用:用于指定的元素进行删除指定的class,如果class存在,那么class就删除,如果class不存则不处理
**参数一:el1进行操作的对象
**参数二:el2获取className的字符
*/
U.UF.EL.removeClass = function (el, str) {
    var _Reg = el.className.match(new RegExp("(\\s|^)" + str + "(\\s|$)")); // ( \\s|^ ) 判断前面是否有空格 (\\s | $ )判断后面是否有空格
    var _b = !!(_Reg);  //两个感叹号为转换为布尔值 以方便做判断
    if (_b) {//判断元素存在指定的class
        el.className = el.className.replace(new RegExp("(\\s|^)" + str + "(\\s|$)"), " ").trim(); // replace方法是替换
    }
}

/*
** 作用:用于判断是否有存在的class,如果有,则返回true,如果没有,则返回false
** @param {element} el
** @param {string} str
*/
U.UF.EL.isHasClass = function (el, str) {
    //判断是否存在指定的classname,如果指定的classname没有出现,则该方法返回 -1。
    if ((el.className).indexOf(str) > -1) {//如果出现了classname,则会出现比-1大的值
        return true; //则返回true
    }
    return false;
}

/*
** 作用:style样式转换 如 text-align => textAlign 或者相反的换
** @param {element} el 进行操作的对象
** @param {string} str 确定循环的范围
*/
U.UF.EL.styleConversion = function (el, str) {
    if (str) {//判断是否有确定循环的范围
        str = [/[A-Z]/g, "-", 0, "toLowerCase"]; //转换的样式或者属性,如textAlign => text-align
    }
    else {//否则的话就进行下面的语句
        str = [/-[a-z ]/g, "", 1, "toUpperCase"]; //转换的样式或者属性,如 text-align => textAlign
    }
    return el.replace(str[0], function (el2) {//利用正则表达式进行转换
        return str[1] + el2.charAt(str[2])[str[3]](); //利用charAt方法返回指定位置的字符
    });
}

/*
**作用:在指定的元素区域通过鼠标进行点击或者是鼠标的其他事件,这个时候我们就需要获取这个鼠标的位置在指定元素的相对位置。
**参数一:el 需要相对位置的元素
*/
U.UF.EL.getMousePosition = function (el) {
    var _eltop = 0, _elleft = 0,
        _mouseevent = event || window.event; //获取事件源
    //如果是手机点击则获取touches[0]对象
    if (_mouseevent.touches && _mouseevent.touches[0]) {
        _mouseevent = _mouseevent.touches[0]; //如果是手机则获取touches[0]对象
    }
    //如果是pc则获取事件源
    else {
        _mouseevent = _mouseevent; //如果是pc则获取事件源
    }
    //获取鼠标的坐标对象
    var _mousex = _mouseevent.clientX || 0, //获取鼠标的X坐标或者是手机点击的X坐标
	_mousey = _mouseevent.clientY || 0; //获取鼠标的Y坐标或者是手机点击的Y坐标
    //循环的找位置
    while (el) {
        _elleft += el.offsetLeft;
        _eltop += el.offsetTop;
        el = el.offsetParent;
    }
    //计算点击的相对位置
    _elx = _mousex - _elleft, //获取鼠标点击的相对位置X坐标
	_ely = _mousey - _eltop; //获取鼠标点击的相对位置的Y坐标
    return { x: _elx, y: _ely}//返回鼠标的相对位置X和Y坐标
}

/*
** 右键菜单处理
** @param {array} 菜单数组 {"name":"","onclick":function(){}} 
** @param {string} 定位到哪个元素
*/
U.UF.EL.rightMenu = function (arr, el, e) {
    var i, _menu;
    if ($("#U_UF_EL_rightmenu")[0]) {
        U.selectEl("#U_UF_EL_rightmenu")[0].remove();
    }
    _menu = $$("div", { "style": { "position": "fixed", "width": "150px", "border": "1px solid #e4e4e4", "backgroundColor": "White", "left": "100px", "display": "none", "z-index": "999" }, "id": "U_UF_EL_rightmenu" }, U.selectEl(el)[0]);
    for (i = 0; i < arr.length; i++) {
        var _div = $$('div', { "style": { "height": "25px", "lineHeight": "25px", "textAlign": "center", "width": "100%", "cursor": "pointer", "padding": "5px 0", "border-bottom": "1px solid rgb(228,228,228)" }, "className": "rightlist" }, _menu);
        U.selectEl(_div).addAttrArray(arr[i]);
    }
    U.selectEl(_menu)[0].style.display = "block";
    U.UF.C.rightClickMenuLocation($(_menu)[0]);
    e = e || window.event;
    var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; //分别兼容ie和chrome
    var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
    var x = e.pageX || (e.clientX + scrollX); //兼容火狐和其他浏览器
    var y = e.pageY || (e.clientY + scrollY);
    var _top = _menu.offsetHeight;
    var _left = _menu.offsetWidth;
    if (_top > y) {
        _menu.style.top = y + "px";
    }
    if (_left > x) {
        _menu.style.left = x + "px";
    }
    U.selectEl(_menu).bind('contextmenu', function (e) {
        U.UF.EV.stopBubble(e);                                    //阻止冒泡
    });
}
;
;
///<jscompress sourcefile="Event.js" />
//处理事件:
Namespace.register("U.UF.EV");
/**
* 统一绑定系统处理函数
* @param fun {function} 执行函数
* 绑定的所有函数可通过   U.UF.EV.systemEventBind,Array 查看
*/
U.UF.EV.systemEventBind = function (fun) {
    U.selectEl('body').bind(fun);
    U.UF.EV.systemEventBind, Array.push(fun);
}

/*
*var a = document.body.aaaa ;
*document.body.aaaa = "aaa"
*  U.UF.EV.boundProperties(HTMLElement.prototype,"aaaa", 
*                          function(){
*                             return this.innerHTML;
*                          },
*                          function(value){
*                              this.innerHTML = value; 
*                          })
*
**  作用:属性添加处理 这里处理例如chrome取消innerText等。
当修改html元素的属性时,可以让他触发一个函数.可以用于双向绑定。当某个变量的值变了,触发回调函数,修改其中的样式。
**  @param {object} obj 需要添加属性的对象
**  @param {string} str 类型的名字
**  @param {function} fun1 get函数处理
**  @param {function} fun2 set函数处理 
*/
U.UF.EV.boundProperties = function (obj, str, fun1, fun2) {
    //判断obj是否已经定义了新的属性
    if (obj.__defineGetter__) {//兼容处理
        obj.__defineGetter__ = (obj, fun1); //__definGetter__用于Getter方法追加定义,函数第一个是getter的名称,第二个参数为getter的函数
        obj.__defineSetter__ = (obj, fun2); //__definSetter__用于Setter方法追加定义,函数第一个是setter的名称,第二个参数为setter的函数
    } else if (Object.defineProperty) {//ie8以上的兼容处理
        //obj.defineProperty是直接在某一个对象上定义一个属性,这个属性可以用来添加或修改现有的属性,obj修改对象,key属性名,
        //{//descriptor}对象用来声明新属性的特性
        //configurable:默认false,表示此属性是否可用delete删除。
        //enumerable: 默认为false,表示此属性是否可被for...in、Object.keys遍历到
        //value:默认undefined,此属性的值,可以是任何JavaScript类型
        //writable:默认为false,此属性是否可被改写
        //get:默认undefined,指定一个函数,当属性被调用时,此函数也被调用,默认为返回属性值
        //set:默认undefined,指定一个函数,当属性被赋值时,此函数也被调用,仅接受一个参数,参数为属性被赋的值
        Object.defineProperty(obj, str, { configurable: true, get: fun1, set: fun2 });
    } else {//ie6-1e7
        obj[str] = fun1; //如果自动获取了属性的对象和类型的名字,则自动调用get函数处理
        obj[str].toString = fun1; //获取的属性对象的类型名进行字符串转换
        //attachEvent事件监听处理,第一个参数是事件类型,第二个参数是处理函数
        obj.attachEvent("onpropertychange", function () {
            if (event.propertyName == obj) {//判断事件对象的属性名是否为需要添加的属性的对象
                //argument用于提供调用当前正在执行的函数,caller返回调用这个函数体的函数,则返回U.UF.EV.boundProperties()
                //再添加一个caller,则返回调用了U.UF.EV.boundProperties()这个函数体的函数
                var _str = arguments.caller.caller;
                obj.detachEvent("onpropertychange", _str); //detachEvent事件监听处理,删除事件,与attachEvent相配对。第一个参数是事件参数,第二个是处理函数
                fun2(obj[str]); //调用set方法去设置新的属性
                obj[str] = fun1; //如果自动获取了属性的对象和类型的名字,则自动调用get函数处理
                obj[str].toString = fun2; //获取的属性对象的类型名进行字符串的转换,并且调用set函数处理
                obj.attachEvent("onpropertychange", _str); //重新建立事件监听处理,重新设置新的属性
            }
        });
    }
}

/*
**  作用:对象添加原型方法,添加新的数据类型,或者在已有数据类型上扩充功能,例如:String,Number,Array,Object,Guid等
**  @param {object} obj 数据类型 例如string、number等
**  @param {string、object} str 当这个参数为string的时候下述函数有效
**  @param {function} fun 原型对应的函数
*/
U.UF.EV.addPrototype = function (obj, str, fun) {
    //判断传值的参数类型是否是string
    if (typeof str == "string") {//如果传值的数据类型是string,则执行以下函数
        obj.prototype[str] = fun; //prototype是添加属性和方法,向obj对象中添加一个属性
    } else {
        var i; //用于循环
        for (i in str) {//循环所有包含了str的个数
            obj.prototype[i] = str[i]; //单个添加包含了str这个类型的属性
        }
    }
}


/**
*当页面滚动到底端的时候执行
*
* @param  {function} fun 滚动到底端需要加载的函数
* @param  {objcet} obj 需要滚动的元素
*/
U.UF.EV.scrollLoad = function (obj, fun) {
    obj.onscroll = function () {//滚动滚轮触发
        clearTimeout(U.UF.EV.scrollLoad.time);
        if (U.UF.EV.scrollLoad.scrollTop(obj) + U.UF.EV.scrollLoad.windowHeight(obj) >= (U.UF.EV.scrollLoad.documentHeight(obj))) {
            U.UF.EV.scrollLoad.time = setTimeout(fun, 100);
        }
    }
}

/**
* 获取页面顶部被卷起来的高度
*/
U.UF.EV.scrollLoad.scrollTop = function (obj) {
    return Math.max(//取最大值
    //chrome
       U.selectEl(obj)[0].scrollTop,
    //firefox/IE
       document.documentElement.scrollTop
    );
}

/**
* 获取页面文档的总高度
*/
U.UF.EV.scrollLoad.documentHeight = function (obj) {
    //现代浏览器(IE9+和其他浏览器)和IE8的document.body.scrollHeight和document.documentElement.scrollHeight都可以
    return Math.max($(obj)[0].scrollHeight, document.documentElement.scrollHeight); //取最大值
}
/**
* 获取页面浏览器视口的高度
*/

U.UF.EV.scrollLoad.windowHeight = function (obj) {
    return U.selectEl(obj)[0].clientHeight;
}

/**
* 页面活动监视,当用户离开页面休息时,停止页面活动(计时器)
*
* @param  {function} 页面聚焦回调函数
* @param  {function} 页面离开的回调
* @return  {string}  获取key对应的值
*/
U.UF.EV.IsActivity = function (fun1, fun2) {
    var _timer;
    //页面聚焦的处理
    if (fun1) {
        //判断鼠标是否在body页面上
        U.selectEl(document.body).mouseenter(function () {
            //由于函数会多次触发,所以做一个计时器进行处理,让函数只触发一次
            if (_timer) {
                window.clearTimeout(_timer);
            }
            _timer = window.setTimeout(fun1);
        });

        //页面聚焦同时为活动页面
        U.UF.EV.addElementEvent("focusin", document, function () {
            //由于函数会多次触发,所以做一个计时器进行处理,让函数只触发一次
            if (_timer) {
                window.clearTimeout(_timer);
            }
            _timer = window.setTimeout(fun1);
        });
    }
    //页面失焦的处理
    if (fun2) {
        //页面不活动的时候处理
        U.UF.EV.addElementEvent("focusout", document, function () {
            var _clientx = event.clientX;  //页面x坐标
            var _clienty = event.clientY; //获取event对象的y坐标

            //判断用户的鼠标是否在制定的范围内,如果在说明活动了当前页面
            if ((!(U.UF.CI.getBrowser().browser == "msie") ||
                (_clientx < 0 || _clientx > US.width || _clienty < 0 || _clienty > US.height))) { //判断鼠标不在页面中
                fun2();
            }
        });
    }
}

/**
* 滚动条滚动到制定的位置
*
* @param  {string}  指定scrollTop的数值
* @param  {function}  需要调整滚动条位置的对象
* @param  {function}  加载成功回调
* @return  {element}  图片元素
*/
U.UF.EV.scrollToPosition = function (str, fun1, fun2) {
    var _isnumber = U.UF.C.isNumber(str); //判断str是否是数字true 或者 false
    //动画移动具体的位置
    if (_isnumber && fun2) {
        U.selectEl(fun1).animate({ "scrollTop": str }, fun2);
    }
    else {
        //设置fun1的内容垂直滚动的像素数
        if (typeof str == "number") {
            fun1.scrollTop = str;
        }
        else {
            str.scrollIntoView(); //sty.scrollIntoView 让当前的元素滚动到浏览器窗口的可视区域内
        }
    } //直接移动过
}

/**
* 自动触发HTMLElement事件 Mouse事件,模拟鼠标点击事件
*
* @param  {element} 触发的元素
* @param  {string} 事件类型
* @return  {object} resize对象
*/
U.UF.EV.simulateMouseClicks = function (el, str) {
    //ie直接执行事件的处理
    if (el.fireEvent) {
        return el.fireEvent("on" + str, window.event);
    }
    //ie以外的浏览器处理事件执行
    else if (document.createEvent) {

        var _mousevent = document.createEvent("MouseEvents"), //创建事件事件
            _event = window.event; //事件处理
        //初始化事件
        if (_event) { //原本已经具有事件event来源的情况下处理
            //执行mouse事件处理
            _mousevent.initMouseEvent(
                            str,
                            true,
                            true,
                            window,
                            _event.detail,
                            _event.screenX,
                            _event.screenY,
                            _event.clientX,
                            _event.clientY,
                            _event.ctrlKey,
                            _event.altKey,
                            _event.shiftKey,
                            _event.metaKey,
                            _event.button,
                            _event.relatedTarget
            );
        }
        else {
            //没有事件来源event的处理
            _mousevent.initMouseEvent(
                            str,
                            true,
                            true,
                            document.defaultView,
                            0,
                            0,
                            0,
                            0,
                            0,
                            false,
                            false,
                            false,
                            false,
                            0,
                            el
            )
        }
        //分发事件
        return el.dispatchEvent(_mousevent);
    }
}

/**
* 自动触发HTMLElement Touch事件
*
* @param  {element} 触发的元素
* @param  {string} 事件类型
* @param  {object} resize对象
*/
U.UF.EV.simulatePhoneTouch = function (el, str, obj) {
    if (el.fireEvent) { //ie事件触发处理
        el.fireEvent("on" + TF);
    }
    else if (document.createEvent) { //h5事件处理
        var i,
            _arr,
            _event = obj || window.event;

        //创建一个touch时间的处理
        if (TouchEvent) { //有TouchEvent的创建方式
            var _touchevent = new TouchEvent(str, _event);
        }
        //其他的创建方式
        else {
            var _touchevent = document.createEvent("TouchEvent");
        }

        //执行事件的方法
        if (_touchevent.initTouchEvent) { //有initTouchEvent执行方法的处理
            var _str = "initTouchEvent";
        }
        else { //initEvent执行方法的处理
            var _str = "initEvent";
        }
        //chrome
        _arr = [
        //chrome
            [
                event.touches, //当前屏幕上所有触摸点的列表
                event.targetTouches, //当前对象上所有触摸点的列表
                event.changedTouches, //涉及当前(引发)事件的触摸点的列表
                str,
                event.view,
                event.screenX,
                event.screenY,
                event.clientX,
                event.clientY,
                event.ctrlKey,
                event.alrKey,
                event.shiftKey,
                event.metaKey
            ],
        //safari
            [
                str,
                true,
                event.cancelable,
                event.view,
                event.detail,
                event.screenX,
                event.screenY,
                event.clientX,
                event.clientY,
                event.ctrlKey,
                event.altKey,
                event.shiftKey,
                event.metaKey,
                event.touches,
                event.targetTouches,
                event.changedTouches,
                event.scale,
                event.rotation
            ],
        //firefox
            [
                str,
                true,
                event.cancelable,
                event.view,
                event.detail,
                event.ctrlKey,
                event.altKey,
                event.shiftKey,
                event.metaKey,
                event.touches,
                event.targetTouches,
                event.changedTouches
                ],
            ];
        //由于浏览器对直接执行事件的兼容有三种方案,这里是对三种方案的循环添加
        for (i = 0; i < _arr.length; i++) {
            //直接执行
            try {
                _touchevent[_str].apply(_touchevent, _arr[i]);
            }
            catch (e) {
            }
            if (_touchevent.type == str) {
                break;
            }
        }

    }
    return el.dispatchEvent(_touchevent); //分发事件
}

/**
* 注册函数事件 Internet Explorer 8 及更早IE版本不支持 addEventListener() 方法,,Opera 7.0 及 Opera 更早版本也不支持。 但是,对于这些不支持该函数的浏览器,你可以使用 attachEvent() 方法来添加事件句柄 
*
* @param  {string} 事件名称
* @param  {element} 添加事件的元素
* @param  {function} 事件触发后调用的函数
* @param  {string} 指定事件是否在捕获或冒泡阶段执行
*/
U.UF.EV.addElementEvent = function (str, el, fun, isbubble) {
    if (el.addEventListener) { //非IE使用
        el.addEventListener(str, fun, isbubble || false);
    }
    else if (el.attachEvent) { //IE
        el.attachEvent("on" + str, fun);
    }
    else {//html5处理
        el["on" + str] = function () {
            el["on" + str]();
            fun();
        }
    }
}

/**
* 取消函数事件
*
* @param  {string} 事件名称
* @param  {element} 添加事件的元素
* @param  {function} 事件触发后调用的函数
* @param  {string} 指定事件是否在捕获或冒泡阶段执行
*/
U.UF.EV.delElementEvent = function (str, el, fun, isbubble) {
    if (el.removeEventListener) { //非IE使用
        el.removeEventListener(str, fun, isbubble || false);
    }
    else if (el.detachEvent) {//IE使用
        el.detachEvent("on" + str, fun);
    }
    else { el["on" + str] = null; } //非元素
}

/**
* 获取事件源 跨iframe搜索,由于我们在点击iframe的时候,不知道事件是从哪个iframe或者来的,所以这里循环iframe找事件的来源
*
*/
U.UF.EV.getEventSource = function () {
    var i, //循环初始化
        _data, //用于储存数据
        _frames = window.frames; //获取window.frames
    var _event = window.event; //获取window.event
    if (!_event) {
        for (i = 0; i < _frames.length; i++) { //循环所有的iframe 获取事件源
            _data = _frames[i]; //得到iframe处理
            //由于非自己站点的iframe会存在跨域处理
            try {
                _event = _data.event; //获取事件
                //如果找到了事件那么就直接break
                if (_event) {
                    break;
                }
            }
            catch (e) { continue; };
        }
    }
    //返回事件源
    return _event;
}

/**
* 阻止冒泡
*/
U.UF.EV.stopBubble = function () {
    var _event = U.UF.EV.getEventSource(); //获取Event
    //调用的时候判断是否有时间的来源
    if (_event) {
        //非ie系列浏览器支持处理事件冒泡的方案
        if (_event.stopPropagation) {
            _event.stopPropagation();
        }
        //ie系列浏览器支持去小事件冒泡处理
        else {
            _event.cancelBubble = true;
        }
    }
}

/**
* 执行mouseout mouseover不冒泡情况,以前是多次触发,现在做到移动进去触发一次,移动出来触发一次
* mouseout||mouseover 冒泡解决
*
* @param  {element} 需要执行的元素 
* @return  {function} 回调函数 
*/
U.UF.EV.stopBubbleMouseOutOrOver = function (el, cb) {
    if (event && "mouseover,mouseout".indexOf(event.type) > -1) { //判断事件源
        var _target = (event.type == "mouseover" ? event.fromElement : event.toElement) || event.relatedTarget, //事件对象
            _bool = U.UF.EL.isChild(el, _target); //判断_target是否是el的子孙节点
        if (!_bool && U.UF.C.isFunction(cb)) { //判断是否在该元素下
            cb();
        }
        return _bool;
    }
}

/**

* 阻止浏览器的默认行为,例如右键菜单,左键选择
*
*/
U.UF.EV.stopDefault = function (e) {
    var _event = e || window.event; //获取window.event对象
    if (_event) {
        //IE中阻止函数器默认动作的方式 
        if (document.all) {
            _event.returnValue = false;
        }
        //阻止默认浏览器动作(W3C) 
        else {
            _event.preventDefault();
        }
        return false;
    }
}

/**
事件委托,本地程序调用客户端程序时会用到。
* 随机产生一个函数 调用后销毁 类似委托
解决跨域问题,以及ajax多个请求,多份实例的问题。
*
* @param  {function} 回调函数
* @param  {array} 回调参数 params1
* @param  {boolean} 执行成功后是否移除委托
* @param  {string} id
* @return  {object} 委托对象
*/
U.UF.EV.eventDelegation = function (cb, params, isremove, id) {
    if (isremove == null) {
        isremove = true;
    }
    var _id = id || "a" + Guid.newGuid(); //唯一识别id
    window[_id] = function () {
        try {
            //判断是否有回调函数
            if (U.UF.C.isFunction(cb)) {
                cb.apply(null, arguments);
            }
            //是否移除事件委托对象
            if (this.isremove) {
                window[_id] = null; //设置对象移除
                delete window[_id]; //清理对象
            }
        }
        catch (e) { }
    }
    return _id;
}

/**
*  页面消息传递,解决跨域问题。
* @param  {function} 跨域iframe传参的回调函数
* @param  {boolean} 是否是发送者,在iframe里面的是接收者,iframe外的是发送者
* @param  {string} 与iframe通讯的唯一识别id,如果是接收多个不同回调的消息,那么需要传参
* @param  {string} 需要跨域的iframe的id
*
*/
U.UF.EV.message = function (fun, issender, id, iframeid) {
    this.fun = fun; //监视消息的函数
    this.id = id || Guid.guidNoDash(); //消息通讯的唯一id
    this.sender = issender; //是否是发送者
    this.iframeid = iframeid; //消息发送到哪个iframe里 接受者没有
    this.iframe = null; //发送给那个iframe的元素
    this.url = ""; //iframe的链接
    U.UF.EV.message.callbacks[this.id] = this; //所有消息记录
    //设置onmessage事件获取浏览器之间的传参
    if ("onmessage" in window) {
        U.UF.EV.addElementEvent("message", window, U.UF.EV.message.getDataAndCallBack);
    }
    //如果是iframe内的发送的处理方式
    if (this.sender) {
        this.iframe = U.selectEl("#" + this.iframeid)[0]; //获取iframe
        this.url = $$("a", { "src": this.iframe.src }).host; //iframe的链接,用于ie跨域传参的时候使用
    }
    //如果是接收者也就是iframe里面的对象的处理方法
    else if (!("onmessage" in window)) {
        U.UF.EV.message.getDataAndCallBack();
    }
}

//这里包含了所有的需要回调的回调函数
U.UF.EV.message.callbacks = [];

/**
*  得到数据的方法
*  @message  {object} 发送者发送的信息
*/
U.UF.EV.message.getDataAndCallBack = function (message) {
    var _data;
    //高版本的浏览器是通过onmessage获取的
    if ("onmessage" in window) {
        _data = message.data; //获取数据
    }
    //低版本的浏览器获取值得处理
    else {
        _data = window.name; //获取数据
    }
    _data = _data.parseJSON(); //传入的数据转化成json处理
    var _fun = U.UF.EV.message.callbacks[_data[1]]; //得到回调函数的类
    //如果类存在,那么调用类的message数据回调方法
    if (_fun) {
        _fun.message(_data[0], _data[1], _data[2]);
    }
}

//message类的原型方法
U.UF.EV.message.prototype = {
    /**
    *  接收消息
    *  @data  {object} 接收的信息
    *  @cookie  {object} 接受者 cookie
    */
    message: function (data, id, cookie) {
        //如果页面监视的是回调函数的处理
        if (U.UF.C.isFunction(this.fun)) {
            this.fun(data, id, cookie);
        }
        //如果是接收者,同时又是在低版本的浏览器下使用的iframe,那么清空iframe的使用
        if (this.sender && !("onmessage" in window)) {
            var _doc = this.obj.contentWindow.document; //重新创建一个document
            _doc.open(); //打开
            _doc.write(""); //整个页面写入空
            _doc.close(); //关闭
        }
    },
    /**
    *  提交消息
    *  @data  {object} 发送者发送的信息
    *  @id  {object} 发送者的id
    *  @cookie  {object} 发送者 cookie
    */
    post: function (data, id, cookie) {
        var _win,
            _message = U.UF.C.jsonToStr([data, id || this.id, cookie]); //拼接传参的参数,由于发送者和接受者都公用这个 所以当接受者给发送者发回消息的时候第二个参数是发送者的id。
        //高版本的iframe发送消息
        if ("onmessage" in window) {
            if (this.sender) {
                //得到iframe传参的域
                try {
                    _win = this.iframe.contentWindow || this.iframe; //如果是发送者,那么获取contentWindow
                }
                catch (e) {
                    _win = this.iframe; //如果是接收者发送回给发送者,那么iframe是parent就不需要获取contentWindow了
                }
            }
            else {
                _win = parent;
            }
            _win.postMessage(_message, "*"); //发送消息
        }
        //低版本的浏览器发送iframe消息
        else {
            //如果是发送者发消息的处理
            if (this.sender) {
                //等待iframe重新加载后处理跨域
                U.UF.DL.iframeLoad(this.iframe, U.UF.C.apply(this, function () {
                    this.iframe.contentWindow.name = _message;  //设置window.name传参值
                    this.iframe.contentWindow.location.href = this.url; //刷新到跨域的页面
                    //重新设置onlaod事件处理等待页面响应
                    U.UF.DL.iframeLoad(this.iframe, U.UF.C.apply(this, function () {
                        U.UF.EV.message.getDataAndCallBack(); //调用iframe返回数据后重新load "about:blank"链接后的回调
                    }));
                }));
                this.iframe.src = "about:blank"; //重新加载iframe
            }
            //接受者的处理
            else {
                window.name = _message; //设置window.name传参值
                window.src = "about:blank"; //
            }
        }
    }
}


/**
*  打印处理函数
*  
*/
U.UF.EV.print = function (el) {
    //    var AllContent = window.document.body.innerHTML; //首先获得元素的html内容,保存当前页面的HTML
    //    var newstr = el.innerHTML; //得到需要打印的元素HTML
    //    document.body.innerHTML = newstr; //把当前页面替换为打印内容HTML
    //    window.print(); //执行打印操作
    //    document.body.innerHTML = AllContent; //还原当前页面

    var iframe = document.createElement('iframe');
    var doc = null;
    iframe.setAttribute('style', 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;');
    document.body.appendChild(iframe);
    doc = iframe.contentWindow.document;
    doc.write('<div>' + el.innerHTML + '</div>');
    doc.close();
    iframe.contentWindow.focus();
    iframe.contentWindow.print();
    if (navigator.userAgent.indexOf("MSIE") > 0) {
        document.body.removeChild(iframe);
    }
}

;
///<jscompress sourcefile="Image.js" />
Namespace.register("U.UF.IMG");

/**
* 图片预加载方法
*
* @param  {string}  需要加载的图片地址
* @param  {function}  预加载回调函数
* @param  {function}  加载成功回调
* @param  {function}  错误处理回调
* @return  {element}  图片元素
*/
U.UF.IMG.imgReady = function (url, URD, ULD, UE) {
    var _UW,
    _UH,
    _UNW, //image对象的width属性
    _UNH, //image对象的height属性
    _UIMG = new Image(); //image对象
    _UOR = function () { //预加载
        _UIMG = _UIMG || this;
        _UNW = _UIMG.width;
        _UNH = _UIMG.height; //获取加载图片的长宽
        if ((_UNW !== _UW || _UNH !== _UH) || _UNH !== 0) {
            if (URD) { URD.call(_UIMG) };
            _UOR.end = true;
        }
    };
    U.selectEl(_UIMG).addAttrArray({ "src": url,
        "onload": function () { //成功加载回调
            setTimeout(function () {
                if (!_UOR.end) { _UOR() };
                if (_UIMG) { _UIMG.onload = _UIMG.onerror = null };
                if (_UIMG && ULD) { ULD.call(_UIMG) };
                _UIMG = null;
            }, 0);
        },
        "onerror": function () { //错误图片处理
            if (U.UF.C.IsNetwork()) {
                if (UE) { UE.call(_UIMG) };
            }
        }
    });
    if (_UIMG) { //说明图片还在加载中
        _UOR(); //执行预加载处理
        if (_UIMG.complete == true) { //判断是否已经成功加载过了 缓存图片处理
            _UIMG.onload(); return;
        }
    }
    if (!_UOR.end) { //添加进入图片大小加载事件
        U.UF.IMG.imgReady._UL.push(_UOR);
        if (U.UF.IMG.imgReady._UIT == null) {
            U.UF.IMG.imgReady._UIT = setInterval(U.UF.IMG.imgReady._URT, 40); //每40毫秒进入
        }
    }
    return _UIMG;
}

U.UF.IMG.imgReady._UIT; //计时器初始化
U.UF.IMG.imgReady._UL = []; //需要预加载的图片集

//去除预加载计时
U.UF.IMG.imgReady._US = function () {
    clearInterval(U.UF.IMG.imgReady._UIT);
    U.UF.IMG.imgReady._UIT = null;
};

//计时加载逐个加载处理
U.UF.IMG.imgReady._URT = function () {
    for (var i = 0; i < U.UF.IMG.imgReady._UL.length; i++) {
        U.UF.IMG.imgReady._UL[i].end ? U.UF.IMG.imgReady._UL.splice(i--, 1) : U.UF.IMG.imgReady._UL[i]();
    }
    if (!U.UF.IMG.imgReady._UL.length) { U.UF.IMG.imgReady._US() };
}


;
///<jscompress sourcefile="Json.js" />

//json综述。此类主要处理以下两种情况的数据。
//1、后台返回的数据形如:{"id":"1","name":"zhangsan"}  称为json数据,在js中称为对象。
//  元素Elements,包括div,a,input等在前端的表现形式是:{"tagname":"input","className":""}
//                                                        {"tagname":"div","className":""}
//2、[
//     {"id":"1","name":"zhangsan"}
//     {"id":"2","name":"lisi"}
//  ]
//
//综上所述,前端元素,数据基本都是{}.所以本数据处理类是针对前端所有对象。

//#region 这里是json操作区域

Namespace.register("U.Json");


//兼容JSON
U.Json.init = function () {
    if (!window.JSON) {
        window.JSON = {
            stringify: U.Json.stringify,
            parse: U.Json.parse
        };
    }
}


//JSON类操作,如果不存在json类,则自己创建一个window.JSON。只有一个地方使用了此函数的parse方法

U.Json.stringify = function (json) {//转化成字符串
    return U.UF.C.jsonToStr(json);
}

U.Json.parse = function (str) {//转化成实体
    return str.parseJSON();
}

/**
* 判断数据是否符合条件
*
* @param  {object || array} 被添加的json对象或者数组
* 
* @param  {object} 比较的对象
* 
* @return  {object} 比较的对象
*/
U.Json.ifExists = function (key1, key2) {
    if (key2 === key1) {
        return true;
    }
    for (var i in key1) {
        if (key1[i] != key2[i]) {
            return false;
        }
    }
    return true;
}

//#region json对象处理类,处理类似下面的json数据
/*{
"_id" : ObjectId("532eab25aa01ee01e2297676"),
"UserID" : "83ddf636-7266-4d15-be11-a7ef89bcac55",
"TNode" : [{
"Name" : "根目录",
"CreateDate" : ISODate("2014-03-23T09:36:37.376Z"),
"Type" : "folder",
"ID" : "e6f3963e-6087-b772-8e54-561353832f7b",
"Deep" : 1.0,
"IsDelete" : false,
"TNode" : [{
"Name" : "Test",
"CreateDate" : ISODate("2014-03-23T09:36:43.526Z"),
"Type" : "folder",
"ID" : "0fb91d00-7c5b-dd79-4f3e-1c2d405611e2",
"IsDelete" : false,
"Deep" : 2.0,
"TNode" : [{
"Name" : "index.htm",
"CreateDate" : ISODate("2014-03-23T09:36:43.548Z"),
"Type" : "file",
"ID" : "929bb945-ca3b-dedd-7077-88d1ce0492e3",
"IsDelete" : false,
"Deep" : 3.0,
"Content" : ""
}],
"IsPublic" : true
}]
}]
}*/
/**
* 添加json对象
*
* @param  {object || array} 被添加的json对象或者数组
* 
* @param  {object} 需要添加的对象值
* 
* @return  {object} 返回添加后新的对象值
实例一
var a = [{username:"a"},{username:"b"},{username:"c"}];
var b = {test:'1'}
U.Json.add(a,b);
    
实例二
var a = {username:"cxs"}
var b = {id:'1'}
U.Json.add(a,b);
*/
U.Json.add = function (obj1, obj2) {
    var i; //循环初始值
    //判断参数obj1是否为对象或者数组,如果是对象,循环添加。
    if (!Array.isArray(obj1)) {//判断是否为数组
        for (i in obj2) {//循环参数obj2对象
            obj1[i] = obj2[i]; //对参数obj1赋值
        }
    }
    //如果参数obj1是数组,为数组中的每一个对象都添加赋值
    else {
        for (i = 0; i < obj1.length; i++) {//循环obj1数组
            U.UF.C.AddObj(obj1[i], obj2); //为数组中的每一个对象元素都添加对象obj2的值。
        }
    }
    //返回添加后新的对象值
    return obj1;
}

//少一个跨层搜索的方法。
//obj json格式 为类似mongodb中的数据,
//key 字符串 是关键字
//value 字符串 是值
U.Json.find = function (obj, key, value) {


}


//#endregion

//#region 处理jsonArray的数据,实质是数组

/**
* 根据条件,删除json数组中指定的json
*
* @param  {array} 被删除的json数组。
* 
* @param  {object} 删除json的数据。
* 
* @return  {object} 返回的删除数据。
            
实例一
var a = [{parentid:1, username:"a"},{parentid:1,username:"b"},{parentid:2,username:"c"}]
var b = {parentid:2,username:"c"}
U.Json.delete(a,b);
*/
U.Json.del = function (obj, key, data) { //删除 允许递归
    data = data || obj; //传递进来的json数据
    var i,
        _deldata,
        _delarray = []; //返回的删除数据。
    //数组删除指定obj条件的元素
    if (Array.isArray(data)) {//数组使用
        for (i = 0; i < data.length; i++) {
            //循环删除 获取移除的元素
            _deldata = U.Json.del(obj, key, data[i]);
            if (_deldata.length) { //判断是否移除了元素,length大于0相当于移除超过一个元素。
                data.splice(i, 1); //数组的系统移除方法
                _delarray = _delarray.concat(_deldata); //把移除的元素添加到变量中
                i--; //由于上面用了循环i++ 移除元素后 数组的下标减一了,所以这里用i--让i回到前面一个循环,这样即使数组删除了一个元素也不会直接跳过下一个元素的循环
            }
        }
    }
    else if (typeof data == "object") { //对象删除
        if (U.Json.ifExists(key, data)) {
            delete data;
            _delarray.push(data);
        }
        else if (key === true) { //递归删除
            for (i in data) {
                _deldata = U.Json.del(obj, key, data[i]); //递归删除该数据
                _delarray = _delarray.concat(_deldata); //把删除的数据追加到变量中
            }
        }
        else if (key && data[key]) { //根据指定的key进行递归删除
            _deldata = U.Json.del(obj, key, data[key]); //根据指定的key递归删除该数据
            _delarray = data.concat(_deldata);
        }
    }
    return _delarray;
}

/**
* 根据条件,查找json数组中指定的json
*
* @param  {array} 需要进行选择的json数组。
* 
* @param  {object} 选择的条件
*
* @param  {number} 选择的个数
* 
* @return  {array} 选择后的结果
实例一
var a = [{ parentid: 1, username: "a" }, { parentid: 1, username: "b" }, { parentid: 2, username: "c" }]
var b = { parentid: 1 }
U.Json.select(a,b,2);
*/
U.Json.select = function (arr, obj, num) {//条件获取
    var i, //判断初始化
        _bool, //用于参数判断
        _res = []; //用于存放选择后的结果
    //判断需要选择的对象是否为数组            
    if (Array.isArray(arr)) {
        //循环json数组
        for (i = 0; i < arr.length; i++) {
            //设置判断默认值
            _bool = true;
            //循环条件
            for (var j in obj) {
                //如果是其中有一个条件不符合要求,修改判断值。
                if (arr[i][j] != obj[j]) {
                    _bool = false;
                }
            }
            //如果所有的条件都成立,则记录数组
            if (_bool) {
                _res.push(arr[i]);
            }
            //判断程序选择的个数是否大于用户的选择个数,如果大于选择个数,跳出循环
            if (_res.length == num) {
                break;
            };
        }
    }
    //返回结果集
    return _res;
}

/**
* 根据条件,查找json数组中指定的json,只获取一个结果集
*
* @param  {array} 需要进行选择的json数组。
* 
* @param  {object} 选择的条件
* 
* @return  {array} 选择后的结果
            
实例一
var a = [{ parentid: 1, username: "a" }, { parentid: 1, username: "b" }, { parentid: 2, username: "c" }]
var b = { parentid: 1 }
U.Json.selectOne(a,b);
*/
U.Json.selectOne = function (arr, obj) {
    return (U.Json.select(arr, obj, 1))[0];
}


/**
* 根据条件,对json数组进行排序,此函数需要移动到数组中。
*
* @param  {array} 需要进行选择的json数组。 
* @param  {number} 排序方式 1正序 -1倒序
* @return  {string} 排序的条件,json数组中的键名  
实例一
var a = [{id:3},{id:1},{id:2}]; 
U.Json.sort(a,"id");
*/
U.Json.sort = function (arr, key, isreverse) { //排序

    isreverse = isreverse || 1;
    //采用数组本身的排序sort方法,此方法比较奇特。
    arr = arr.sort(function (obj1, obj2) {
        var _value,
            _type, //比较大小的类型
            _value1 = obj1[key],
            _value2 = obj2[key],
            _isobj = U.UF.C.isObject(obj1); //判断比较的大小是否为对象


        //对象的大小匹配
        if (_isobj) {
            _type = (typeof (obj1[key] || obj2[key])).capitalizeFirstLetter(); //由于类型的值有可能是null或者是undefined,判断两种比较安全
        }
        //非对象的处理方式 U.UF.Ut.compare+type 是一些列的对象比较大小的方法
        else {
            _type = (typeof obj1).capitalizeFirstLetter();
        }
        //数字大小比较
        if (_type == "Number") {
            _value = _value1 > _value2;
        }
        //时间大小比较
        else if (_type == "Date") {
            _value = U.UF.D.SizeComparison(_value1, _value2);
        }
        //字符串大小比较
        else if (_type == "String") {
            _value = _value1.localeCompare(_value2) == 1;
        }
        //服务器的值可能是null,没有类型比较默认第一个比第二个大
        else {
            _value = true;
        }
        //isreverse 用于判断倒序还是正序,如果是-1就是倒序,如果是1就是正序,需要返回这个值给数组的sort函数,比较奇特
        _value = isreverse * (_value ? 1 : -1);
        return _value;
    });
    return arr;
}


/**
* 根据条件,对json数组进行排序,此函数注释有问题
*
* @param  {array} obj数组
* @param  {string} 关键字 
*/
U.Json.toKeyArray = function (arr, key) {
    var i,
        _returnarr = []; //数组存储数据
    //循环写入数据
    for (i = 0; i < arr.length; i++) {
        _returnarr.push(arr[i][key]);
    }
    //返回数组
    return _returnarr;
}

/**
* 根据条件,对json数组进行排序,此函数注释有问题
*
* @param  {array} obj数组
* @param  {object} key value的条件 
* @param  {number} 关键字 
*/
U.Json.like = function (arr, obj, num) {
    var i, //判断初始化
        _bool, //用于参数判断
        _res = []; //用于存放选择后的结果
    //判断需要选择的对象是否为数组            
    if (Array.isArray(arr)) {
        //循环json数组
        for (i = 0; i < arr.length; i++) {
            //设置判断默认值
            _bool = false;
            //循环条件
            for (var j in obj) {
                //如果是其中有一个条件不符合要求,修改判断值。
                if (arr[i][j] && (arr[i][j].indexOf(obj[j]) > -1 || obj[j].indexOf(arr[i][j]) > -1)) {
                    _bool = true;
                }
            }
            //如果所有的条件都成立,则记录数组
            if (_bool) {
                _res.push(arr[i]);
            }
            //判断程序选择的个数是否大于用户的选择个数,如果大于选择个数,跳出循环
            if (_res.length == num) {
                break;
            };
        }
        //返回结果集
        return _res;
    }
}
//#endregion
;
///<jscompress sourcefile="Math.js" />
//#region 函数区域
Namespace.register("U.UF.Math");

/**
* 获取一个随机数
*
* @param  {number} 随机数的长度
* @return  {number} 随机数
*/
U.UF.Math.getRandom = function (n) {
    return Math.floor(Math.random() * n + 1);
}

/**
* 获取两个数字间的随机数
*
* @param  {number} 位置的开始
* @param  {number} 位置的结束
* @return  {number} 随机数
*/
U.UF.Math.randomRange = function (m, n) {
    return Math.floor(Math.random() * Math.abs(n - m)) + (m > n ? n : m);
}

/**
* 冒泡排序法的封装
*
* @param  {array} 排序数组
* @param  {string} 排序类型 
* @param  {function} 判断执行函数
* @param  {number} 是否是升序降序
----------[-1] 升序
----------[1] 降序
*/
U.UF.Math.sequence = function (arr, str, fun, num) {
    if (arr) {//是否存在数组
        var _num;
        arr = arr.sort(function (obj1, obj2) {//arr.sort()根据条件,对json数组进行排序
            if (fun(obj1[str], obj2[str])) {//是否是升序降序
                _num = (-1) * (num || 1); //num=-1升序
            } else {
                _num = 1 * (num || 1); //num=1 降序
            }
            return _num;
        });
        return arr;
    };
}

/**
*浮点数运算函数
JavaScript浮点运算的一个bug。 比如:7*0.8 JavaScript算出来就是:5.6000000000000005
* 数字计算 解决浮点的bug
*
* @param  {number} 数字1
* @param  {number} 数字2
* @param  {string} 连系符号 + - * /
*/
U.UF.Math.floatOperate = function (number1, number2, operator) {
    var i, //循环初始化
        _pow, ////用于存放数据的变量
        _strarr = [String(number1), String(number2)]; //用于存放数据的数组
    //获取变成整数差几位
    for (i = 0; i < 2; i++) {
        _strarr[i + 2] = _strarr[i].length - _strarr[i].indexOf(".") - 1;
    }
    //变成整数的幂
    _pow = Math.pow(10, Math.max(_strarr[2], _strarr[3]));
    //运算得出结果
    return (eval("0," + _strarr[0] * _pow + operator + _strarr[1] * _pow)) / _pow;
}
;
///<jscompress sourcefile="Navigation.js" />
/*
前进后退处理区域
用于场景
1、导航前进后退处理
2、记录用户步骤处理
3、url前进后退处理
*/
Namespace.register("U.UF.N");

//#region 前进后退使用处理区域

U.UF.N.goList = {}; //前进后退处理
U.UF.N.route = null //url处理

/**
* 前进后退公开调用区域
*
* @param  {string} 前进后退在指定的域
* @param  {boolean} 是否重新加载
*/
U.UF.N.createNav = function (str, bool) {
    var _obj = U.UF.N.goList;
    //根据类类型 获取前进后退类
    if (_obj[str] && bool !== true) { //已经存在域的前进后退
        return _obj[str].context;
    }
    else { //创建一个新的前进后退处理
        return new U.UF.N.initNav(str);
    }
}

/**
* 注册前进后退
*
* @param  {string} 前进后退在指定的域 如 disk 那就在disk导航
*/
U.UF.N.initNav = function (str) {
    /*
    描述 
    -----OF: 当前前进后退集合
    -----OL: 前进后退所在的位置
    -----UT: 当前的域
    */
    this.cb = [];
    this.length = 0;
    this.context = this;
    U.UF.N.goList[str] = this; //添加到集合里面
}

/**
* 添加前进后退
*
* @param  {function} 前进后退函数添加
* @param  {string} 前进后退在指定的域
*/
U.UF.N.addEvent = function (callback, str) {
    var _goList = U.UF.N.createNav(str); // 获取前进后退类
    _goList.addHandleEvent(callback);  // 注册前进后退事件
    callback(); //添加执行前进后退
}

/**
* 添加前进后退事件
*
* @param  {function} 前进后退函数添加
*/
U.UF.N.addHandleEvent = function (callback) {
    this.cb.splice(this.length, this.cb.length - this.length, callback); //添加一个回调函数
    // this.cb.length - this.length 始终为0
    this.length++; //位置加一
}

/**
* 前进后退统一处理区
* 该函数必须得先后退才能前进
* 
* @param  {number} 前进后退处理参数
----------1 后退处理
----------0 前进处理
*/
U.UF.N.handle = function (num) {
    var _callback = this.cb[this.length - num * 2]; //获取前进后退事件
    // 若 num 为1 则 this.cb[this.length - num * 2] 为 this.cb[this.length - 1]
    // 若 num 为0 则 this.cb[this.length - num * 2] 为 this.cb[this.length]
    if (_callback) {
        _callback();
        this.length += ((-num * 2) + 1); //前进后退执行
        // 若 num 为1 则 将 this.length - 1
        // 若 num 为0 则 将 this.length + 1
    }
}

/**
* 后退执行
*
* @param  {string} 前进后退在指定的域
*/
U.UF.N.backOff = function (str) {
    U.UF.N.goList[str]["context"].handle(1);
}

/**
* 
* 前进执行
*
* @param  {string} 前进后退在指定的域
*/
U.UF.N.goAhead = function (str) {
    U.UF.N.goList[str]["context"].handle(0);
}

/**
* 
* 获取当前位置
*
* @param  {string} 前进后退在指定的域
* @return {object} 返回位置信息 
*                  数据结构如下: {
*                       count: 总计层级,
*                       now: 当前层级(1为根级导航  当当前层级等于总计层级时为最后一级导航)
*                   }
*/
U.UF.N.getLocation = function (str) {
    return {
        count: U.UF.N.goList[str].cb.length,
        now: U.UF.N.goList[str].length
    }
}

//设置原型 运行实例化使用
U.UF.N.initNav.prototype = {
    addEvent: U.UF.N.addEvent,
    addHandleEvent: U.UF.N.addHandleEvent,
    handle: U.UF.N.handle,
    backOff: U.UF.N.backOff,
    goAhead: U.UF.N.goAhead
}

//#endregion

//#region 网页路由使用

//
U.UF.N.isActive = false;

/*
*  作用:初始化函数,每次修改hash值的时候都会触发这个函数,调用onhashchange事件
*  @param {callback} fun 回调函数,进行数据的操作
*/
U.UF.N.route = function (fun) {
    //当浏览器前进后退修改hash值时,触发onhashchange事件
    if (document.all && !document.documentMode) { //辨别IE,IE8才有documentMode  
        /* 低于IE8的IE系列采用定时器监听 */
        setInterval(function () { U.UF.N.changeHashCallBack(fun) }, 100);  //每隔0.1秒监听一次hash值,发生变化时,触发U.UF.N.changeHashCallBack()这个函数
    }
    else {
        window.onhashchange = function () { U.UF.N.changeHashCallBack(fun) };  //当hash值改变时,触发函数U.UF.N.changeHashCallBack()
    }
}

/*
*  作用:给需要添加hash的元素添加hash值
*  @param {string} hashname 添加hash的name
*/
U.UF.N.addHash = function (hashname) {
    U.UF.N.setHash(hashname); //给需要添加hash值的元素设置hash值,参数为添加hash的name
}

/*
* 作用:给需要添加hash值的元素设置hash值
* @param {element} id 添加hash的值 
*/
U.UF.N.setHash = function (id) {
    U.UF.N.isActive = true; //设置成程序主动模式
    location.hash = id; //给当前的hash值设值为用户自定义的hash的name
    //计时器处理
    setTimeout(function () {
        //计时器处理,等浏览器响应hash后设置为非主动模式
        U.UF.N.isActive = false;
    }, 10)
}
/*
* 作用:获取当前的hash值
*/
U.UF.N.getHash = function () {
    var _nowhash = location.hash; //获取当前的hash值
    if (!_nowhash) {//判断是否有这个hash值
        return ''; //如果没有返回空
    }
    else {//如果有
        return location.hash; //返回当前的hash值
    }
}
/*
*  作用:当hash改变之后,会触发这个函数
*/
U.UF.N.changeHashCallBack = function (fun) {
    //如果不是通过程序添加的处理,而是用户自己输入到地址栏的处理
    if (!U.UF.N.isActive) {
        var _newhash = U.UF.N.getHash(); //获取当前的hash值
        var _hash = _newhash.substr('1'); //获取hash值的#符号后面的内容
        if (_hash != "") { //判断U.UF.N.Data的json数据中是否存在这个hash值
            fun(_hash);
        }
        else if (_hash == "") {
            window.history.forward(1); //如果是,禁止后退
        }
    }
}

//#endregion
;
///<jscompress sourcefile="QRCode.js" />
Namespace.register("U.UF.QR"); //二维码命名空间
/**
* 生成二维码
*
* @param  {number} 二维码元素宽度
* @param  {number} 二维码元素高度
* @param  {string} 二维码背景色
* @param  {string} 二维码前景色
* @param  {string || object} 二维码内容
* @param  {object} 二维码追加元素
*/
U.UF.QR.generate = function (w, h, d, l, v, g) {
    //清空生成地
    g.innerHTML = "";
    //创建一个对象 
    var qrcode = new QRCode(g, {
        width: w,
        height: h,
        colorDark: d,
        colorLight: l,
        correctLevel: QRCode.CorrectLevel.H  //容错率
    });
    U.UF.QR.makeCode = function (v) {
        //绘制
        qrcode.makeCode(v);
    }
    U.UF.QR.makeCode(v);
}
/**
* @fileoverview
* - Using the 'QRCode for Javascript library'
* - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
* - this library has no dependencies.
* 
* @author davidshimjs
* @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a>
* @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a>
*/
var QRCode;

(function () {
    //---------------------------------------------------------------------
    // QRCode for JavaScript
    //
    // Copyright (c) 2009 Kazuhiko Arase
    //
    // URL: http://www.d-project.com/
    //
    // Licensed under the MIT license:
    //   http://www.opensource.org/licenses/mit-license.php
    //
    // The word "QR Code" is registered trademark of 
    // DENSO WAVE INCORPORATED
    //   http://www.denso-wave.com/qrcode/faqpatent-e.html
    //
    //---------------------------------------------------------------------
    function QR8bitByte(data) {
        this.mode = QRMode.MODE_8BIT_BYTE;
        this.data = data;
        this.parsedData = [];

        // Added to support UTF-8 Characters
        for (var i = 0, l = this.data.length; i < l; i++) {
            var byteArray = [];
            var code = this.data.charCodeAt(i);

            if (code > 0x10000) {
                byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
                byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
                byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
                byteArray[3] = 0x80 | (code & 0x3F);
            } else if (code > 0x800) {
                byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
                byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
                byteArray[2] = 0x80 | (code & 0x3F);
            } else if (code > 0x80) {
                byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
                byteArray[1] = 0x80 | (code & 0x3F);
            } else {
                byteArray[0] = code;
            }

            this.parsedData.push(byteArray);
        }

        this.parsedData = Array.prototype.concat.apply([], this.parsedData);

        if (this.parsedData.length != this.data.length) {
            this.parsedData.unshift(191);
            this.parsedData.unshift(187);
            this.parsedData.unshift(239);
        }
    }

    QR8bitByte.prototype = {
        getLength: function (buffer) {
            return this.parsedData.length;
        },
        write: function (buffer) {
            for (var i = 0, l = this.parsedData.length; i < l; i++) {
                buffer.put(this.parsedData[i], 8);
            }
        }
    };

    function QRCodeModel(typeNumber, errorCorrectLevel) {
        this.typeNumber = typeNumber;
        this.errorCorrectLevel = errorCorrectLevel;
        this.modules = null;
        this.moduleCount = 0;
        this.dataCache = null;
        this.dataList = [];
    }

    QRCodeModel.prototype = { addData: function (data) { var newData = new QR8bitByte(data); this.dataList.push(newData); this.dataCache = null; }, isDark: function (row, col) {
        if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { throw new Error(row + "," + col); }
        return this.modules[row][col];
    }, getModuleCount: function () { return this.moduleCount; }, make: function () { this.makeImpl(false, this.getBestMaskPattern()); }, makeImpl: function (test, maskPattern) {
        this.moduleCount = this.typeNumber * 4 + 17; this.modules = new Array(this.moduleCount); for (var row = 0; row < this.moduleCount; row++) { this.modules[row] = new Array(this.moduleCount); for (var col = 0; col < this.moduleCount; col++) { this.modules[row][col] = null; } }
        this.setupPositionProbePattern(0, 0); this.setupPositionProbePattern(this.moduleCount - 7, 0); this.setupPositionProbePattern(0, this.moduleCount - 7); this.setupPositionAdjustPattern(); this.setupTimingPattern(); this.setupTypeInfo(test, maskPattern); if (this.typeNumber >= 7) { this.setupTypeNumber(test); }
        if (this.dataCache == null) { this.dataCache = QRCodeModel.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); }
        this.mapData(this.dataCache, maskPattern);
    }, setupPositionProbePattern: function (row, col) { for (var r = -1; r <= 7; r++) { if (row + r <= -1 || this.moduleCount <= row + r) continue; for (var c = -1; c <= 7; c++) { if (col + c <= -1 || this.moduleCount <= col + c) continue; if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) { this.modules[row + r][col + c] = true; } else { this.modules[row + r][col + c] = false; } } } }, getBestMaskPattern: function () {
        var minLostPoint = 0; var pattern = 0; for (var i = 0; i < 8; i++) { this.makeImpl(true, i); var lostPoint = QRUtil.getLostPoint(this); if (i == 0 || minLostPoint > lostPoint) { minLostPoint = lostPoint; pattern = i; } }
        return pattern;
    }, createMovieClip: function (target_mc, instance_name, depth) {
        var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); var cs = 1; this.make(); for (var row = 0; row < this.modules.length; row++) { var y = row * cs; for (var col = 0; col < this.modules[row].length; col++) { var x = col * cs; var dark = this.modules[row][col]; if (dark) { qr_mc.beginFill(0, 100); qr_mc.moveTo(x, y); qr_mc.lineTo(x + cs, y); qr_mc.lineTo(x + cs, y + cs); qr_mc.lineTo(x, y + cs); qr_mc.endFill(); } } }
        return qr_mc;
    }, setupTimingPattern: function () {
        for (var r = 8; r < this.moduleCount - 8; r++) {
            if (this.modules[r][6] != null) { continue; }
            this.modules[r][6] = (r % 2 == 0);
        }
        for (var c = 8; c < this.moduleCount - 8; c++) {
            if (this.modules[6][c] != null) { continue; }
            this.modules[6][c] = (c % 2 == 0);
        }
    }, setupPositionAdjustPattern: function () {
        var pos = QRUtil.getPatternPosition(this.typeNumber); for (var i = 0; i < pos.length; i++) {
            for (var j = 0; j < pos.length; j++) {
                var row = pos[i]; var col = pos[j]; if (this.modules[row][col] != null) { continue; }
                for (var r = -2; r <= 2; r++) { for (var c = -2; c <= 2; c++) { if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) { this.modules[row + r][col + c] = true; } else { this.modules[row + r][col + c] = false; } } }
            }
        }
    }, setupTypeNumber: function (test) {
        var bits = QRUtil.getBCHTypeNumber(this.typeNumber); for (var i = 0; i < 18; i++) { var mod = (!test && ((bits >> i) & 1) == 1); this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod; }
        for (var i = 0; i < 18; i++) { var mod = (!test && ((bits >> i) & 1) == 1); this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; }
    }, setupTypeInfo: function (test, maskPattern) {
        var data = (this.errorCorrectLevel << 3) | maskPattern; var bits = QRUtil.getBCHTypeInfo(data); for (var i = 0; i < 15; i++) { var mod = (!test && ((bits >> i) & 1) == 1); if (i < 6) { this.modules[i][8] = mod; } else if (i < 8) { this.modules[i + 1][8] = mod; } else { this.modules[this.moduleCount - 15 + i][8] = mod; } }
        for (var i = 0; i < 15; i++) { var mod = (!test && ((bits >> i) & 1) == 1); if (i < 8) { this.modules[8][this.moduleCount - i - 1] = mod; } else if (i < 9) { this.modules[8][15 - i - 1 + 1] = mod; } else { this.modules[8][15 - i - 1] = mod; } }
        this.modules[this.moduleCount - 8][8] = (!test);
    }, mapData: function (data, maskPattern) {
        var inc = -1; var row = this.moduleCount - 1; var bitIndex = 7; var byteIndex = 0; for (var col = this.moduleCount - 1; col > 0; col -= 2) {
            if (col == 6) col--; while (true) {
                for (var c = 0; c < 2; c++) {
                    if (this.modules[row][col - c] == null) {
                        var dark = false; if (byteIndex < data.length) { dark = (((data[byteIndex] >>> bitIndex) & 1) == 1); }
                        var mask = QRUtil.getMask(maskPattern, row, col - c); if (mask) { dark = !dark; }
                        this.modules[row][col - c] = dark; bitIndex--; if (bitIndex == -1) { byteIndex++; bitIndex = 7; }
                    }
                }
                row += inc; if (row < 0 || this.moduleCount <= row) { row -= inc; inc = -inc; break; }
            }
        }
    }
    }; QRCodeModel.PAD0 = 0xEC; QRCodeModel.PAD1 = 0x11; QRCodeModel.createData = function (typeNumber, errorCorrectLevel, dataList) {
        var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); var buffer = new QRBitBuffer(); for (var i = 0; i < dataList.length; i++) { var data = dataList[i]; buffer.put(data.mode, 4); buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); data.write(buffer); }
        var totalDataCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalDataCount += rsBlocks[i].dataCount; }
        if (buffer.getLengthInBits() > totalDataCount * 8) {
            throw new Error("code length overflow. ("
	+ buffer.getLengthInBits()
	+ ">"
	+ totalDataCount * 8
	+ ")");
        }
        if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { buffer.put(0, 4); }
        while (buffer.getLengthInBits() % 8 != 0) { buffer.putBit(false); }
        while (true) {
            if (buffer.getLengthInBits() >= totalDataCount * 8) { break; }
            buffer.put(QRCodeModel.PAD0, 8); if (buffer.getLengthInBits() >= totalDataCount * 8) { break; }
            buffer.put(QRCodeModel.PAD1, 8);
        }
        return QRCodeModel.createBytes(buffer, rsBlocks);
    }; QRCodeModel.createBytes = function (buffer, rsBlocks) {
        var offset = 0; var maxDcCount = 0; var maxEcCount = 0; var dcdata = new Array(rsBlocks.length); var ecdata = new Array(rsBlocks.length); for (var r = 0; r < rsBlocks.length; r++) {
            var dcCount = rsBlocks[r].dataCount; var ecCount = rsBlocks[r].totalCount - dcCount; maxDcCount = Math.max(maxDcCount, dcCount); maxEcCount = Math.max(maxEcCount, ecCount); dcdata[r] = new Array(dcCount); for (var i = 0; i < dcdata[r].length; i++) { dcdata[r][i] = 0xff & buffer.buffer[i + offset]; }
            offset += dcCount; var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); var modPoly = rawPoly.mod(rsPoly); ecdata[r] = new Array(rsPoly.getLength() - 1); for (var i = 0; i < ecdata[r].length; i++) { var modIndex = i + modPoly.getLength() - ecdata[r].length; ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0; }
        }
        var totalCodeCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalCodeCount += rsBlocks[i].totalCount; }
        var data = new Array(totalCodeCount); var index = 0; for (var i = 0; i < maxDcCount; i++) { for (var r = 0; r < rsBlocks.length; r++) { if (i < dcdata[r].length) { data[index++] = dcdata[r][i]; } } }
        for (var i = 0; i < maxEcCount; i++) { for (var r = 0; r < rsBlocks.length; r++) { if (i < ecdata[r].length) { data[index++] = ecdata[r][i]; } } }
        return data;
    }; var QRMode = { MODE_NUMBER: 1 << 0, MODE_ALPHA_NUM: 1 << 1, MODE_8BIT_BYTE: 1 << 2, MODE_KANJI: 1 << 3 }; var QRErrorCorrectLevel = { L: 1, M: 0, Q: 3, H: 2 }; var QRMaskPattern = { PATTERN000: 0, PATTERN001: 1, PATTERN010: 2, PATTERN011: 3, PATTERN100: 4, PATTERN101: 5, PATTERN110: 6, PATTERN111: 7 }; var QRUtil = { PATTERN_POSITION_TABLE: [[], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50], [6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78], [6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102], [6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122], [6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138], [6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154], [6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170]], G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), getBCHTypeInfo: function (data) {
        var d = data << 10; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))); }
        return ((data << 10) | d) ^ QRUtil.G15_MASK;
    }, getBCHTypeNumber: function (data) {
        var d = data << 12; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))); }
        return (data << 12) | d;
    }, getBCHDigit: function (data) {
        var digit = 0; while (data != 0) { digit++; data >>>= 1; }
        return digit;
    }, getPatternPosition: function (typeNumber) { return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; }, getMask: function (maskPattern, i, j) { switch (maskPattern) { case QRMaskPattern.PATTERN000: return (i + j) % 2 == 0; case QRMaskPattern.PATTERN001: return i % 2 == 0; case QRMaskPattern.PATTERN010: return j % 3 == 0; case QRMaskPattern.PATTERN011: return (i + j) % 3 == 0; case QRMaskPattern.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; case QRMaskPattern.PATTERN101: return (i * j) % 2 + (i * j) % 3 == 0; case QRMaskPattern.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 == 0; case QRMaskPattern.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 == 0; default: throw new Error("bad maskPattern:" + maskPattern); } }, getErrorCorrectPolynomial: function (errorCorrectLength) {
        var a = new QRPolynomial([1], 0); for (var i = 0; i < errorCorrectLength; i++) { a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)); }
        return a;
    }, getLengthInBits: function (mode, type) { if (1 <= type && type < 10) { switch (mode) { case QRMode.MODE_NUMBER: return 10; case QRMode.MODE_ALPHA_NUM: return 9; case QRMode.MODE_8BIT_BYTE: return 8; case QRMode.MODE_KANJI: return 8; default: throw new Error("mode:" + mode); } } else if (type < 27) { switch (mode) { case QRMode.MODE_NUMBER: return 12; case QRMode.MODE_ALPHA_NUM: return 11; case QRMode.MODE_8BIT_BYTE: return 16; case QRMode.MODE_KANJI: return 10; default: throw new Error("mode:" + mode); } } else if (type < 41) { switch (mode) { case QRMode.MODE_NUMBER: return 14; case QRMode.MODE_ALPHA_NUM: return 13; case QRMode.MODE_8BIT_BYTE: return 16; case QRMode.MODE_KANJI: return 12; default: throw new Error("mode:" + mode); } } else { throw new Error("type:" + type); } }, getLostPoint: function (qrCode) {
        var moduleCount = qrCode.getModuleCount(); var lostPoint = 0; for (var row = 0; row < moduleCount; row++) {
            for (var col = 0; col < moduleCount; col++) {
                var sameCount = 0; var dark = qrCode.isDark(row, col); for (var r = -1; r <= 1; r++) {
                    if (row + r < 0 || moduleCount <= row + r) { continue; }
                    for (var c = -1; c <= 1; c++) {
                        if (col + c < 0 || moduleCount <= col + c) { continue; }
                        if (r == 0 && c == 0) { continue; }
                        if (dark == qrCode.isDark(row + r, col + c)) { sameCount++; }
                    }
                }
                if (sameCount > 5) { lostPoint += (3 + sameCount - 5); }
            }
        }
        for (var row = 0; row < moduleCount - 1; row++) { for (var col = 0; col < moduleCount - 1; col++) { var count = 0; if (qrCode.isDark(row, col)) count++; if (qrCode.isDark(row + 1, col)) count++; if (qrCode.isDark(row, col + 1)) count++; if (qrCode.isDark(row + 1, col + 1)) count++; if (count == 0 || count == 4) { lostPoint += 3; } } }
        for (var row = 0; row < moduleCount; row++) { for (var col = 0; col < moduleCount - 6; col++) { if (qrCode.isDark(row, col) && !qrCode.isDark(row, col + 1) && qrCode.isDark(row, col + 2) && qrCode.isDark(row, col + 3) && qrCode.isDark(row, col + 4) && !qrCode.isDark(row, col + 5) && qrCode.isDark(row, col + 6)) { lostPoint += 40; } } }
        for (var col = 0; col < moduleCount; col++) { for (var row = 0; row < moduleCount - 6; row++) { if (qrCode.isDark(row, col) && !qrCode.isDark(row + 1, col) && qrCode.isDark(row + 2, col) && qrCode.isDark(row + 3, col) && qrCode.isDark(row + 4, col) && !qrCode.isDark(row + 5, col) && qrCode.isDark(row + 6, col)) { lostPoint += 40; } } }
        var darkCount = 0; for (var col = 0; col < moduleCount; col++) { for (var row = 0; row < moduleCount; row++) { if (qrCode.isDark(row, col)) { darkCount++; } } }
        var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; lostPoint += ratio * 10; return lostPoint;
    }
    }; var QRMath = { glog: function (n) {
        if (n < 1) { throw new Error("glog(" + n + ")"); }
        return QRMath.LOG_TABLE[n];
    }, gexp: function (n) {
        while (n < 0) { n += 255; }
        while (n >= 256) { n -= 255; }
        return QRMath.EXP_TABLE[n];
    }, EXP_TABLE: new Array(256), LOG_TABLE: new Array(256)
    }; for (var i = 0; i < 8; i++) { QRMath.EXP_TABLE[i] = 1 << i; }
    for (var i = 8; i < 256; i++) { QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8]; }
    for (var i = 0; i < 255; i++) { QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; }
    function QRPolynomial(num, shift) {
        if (num.length == undefined) { throw new Error(num.length + "/" + shift); }
        var offset = 0; while (offset < num.length && num[offset] == 0) { offset++; }
        this.num = new Array(num.length - offset + shift); for (var i = 0; i < num.length - offset; i++) { this.num[i] = num[i + offset]; }
    }
    QRPolynomial.prototype = { get: function (index) { return this.num[index]; }, getLength: function () { return this.num.length; }, multiply: function (e) {
        var num = new Array(this.getLength() + e.getLength() - 1); for (var i = 0; i < this.getLength(); i++) { for (var j = 0; j < e.getLength(); j++) { num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j))); } }
        return new QRPolynomial(num, 0);
    }, mod: function (e) {
        if (this.getLength() - e.getLength() < 0) { return this; }
        var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0)); var num = new Array(this.getLength()); for (var i = 0; i < this.getLength(); i++) { num[i] = this.get(i); }
        for (var i = 0; i < e.getLength(); i++) { num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio); }
        return new QRPolynomial(num, 0).mod(e);
    }
    }; function QRRSBlock(totalCount, dataCount) { this.totalCount = totalCount; this.dataCount = dataCount; }
    QRRSBlock.RS_BLOCK_TABLE = [[1, 26, 19], [1, 26, 16], [1, 26, 13], [1, 26, 9], [1, 44, 34], [1, 44, 28], [1, 44, 22], [1, 44, 16], [1, 70, 55], [1, 70, 44], [2, 35, 17], [2, 35, 13], [1, 100, 80], [2, 50, 32], [2, 50, 24], [4, 25, 9], [1, 134, 108], [2, 67, 43], [2, 33, 15, 2, 34, 16], [2, 33, 11, 2, 34, 12], [2, 86, 68], [4, 43, 27], [4, 43, 19], [4, 43, 15], [2, 98, 78], [4, 49, 31], [2, 32, 14, 4, 33, 15], [4, 39, 13, 1, 40, 14], [2, 121, 97], [2, 60, 38, 2, 61, 39], [4, 40, 18, 2, 41, 19], [4, 40, 14, 2, 41, 15], [2, 146, 116], [3, 58, 36, 2, 59, 37], [4, 36, 16, 4, 37, 17], [4, 36, 12, 4, 37, 13], [2, 86, 68, 2, 87, 69], [4, 69, 43, 1, 70, 44], [6, 43, 19, 2, 44, 20], [6, 43, 15, 2, 44, 16], [4, 101, 81], [1, 80, 50, 4, 81, 51], [4, 50, 22, 4, 51, 23], [3, 36, 12, 8, 37, 13], [2, 116, 92, 2, 117, 93], [6, 58, 36, 2, 59, 37], [4, 46, 20, 6, 47, 21], [7, 42, 14, 4, 43, 15], [4, 133, 107], [8, 59, 37, 1, 60, 38], [8, 44, 20, 4, 45, 21], [12, 33, 11, 4, 34, 12], [3, 145, 115, 1, 146, 116], [4, 64, 40, 5, 65, 41], [11, 36, 16, 5, 37, 17], [11, 36, 12, 5, 37, 13], [5, 109, 87, 1, 110, 88], [5, 65, 41, 5, 66, 42], [5, 54, 24, 7, 55, 25], [11, 36, 12], [5, 122, 98, 1, 123, 99], [7, 73, 45, 3, 74, 46], [15, 43, 19, 2, 44, 20], [3, 45, 15, 13, 46, 16], [1, 135, 107, 5, 136, 108], [10, 74, 46, 1, 75, 47], [1, 50, 22, 15, 51, 23], [2, 42, 14, 17, 43, 15], [5, 150, 120, 1, 151, 121], [9, 69, 43, 4, 70, 44], [17, 50, 22, 1, 51, 23], [2, 42, 14, 19, 43, 15], [3, 141, 113, 4, 142, 114], [3, 70, 44, 11, 71, 45], [17, 47, 21, 4, 48, 22], [9, 39, 13, 16, 40, 14], [3, 135, 107, 5, 136, 108], [3, 67, 41, 13, 68, 42], [15, 54, 24, 5, 55, 25], [15, 43, 15, 10, 44, 16], [4, 144, 116, 4, 145, 117], [17, 68, 42], [17, 50, 22, 6, 51, 23], [19, 46, 16, 6, 47, 17], [2, 139, 111, 7, 140, 112], [17, 74, 46], [7, 54, 24, 16, 55, 25], [34, 37, 13], [4, 151, 121, 5, 152, 122], [4, 75, 47, 14, 76, 48], [11, 54, 24, 14, 55, 25], [16, 45, 15, 14, 46, 16], [6, 147, 117, 4, 148, 118], [6, 73, 45, 14, 74, 46], [11, 54, 24, 16, 55, 25], [30, 46, 16, 2, 47, 17], [8, 132, 106, 4, 133, 107], [8, 75, 47, 13, 76, 48], [7, 54, 24, 22, 55, 25], [22, 45, 15, 13, 46, 16], [10, 142, 114, 2, 143, 115], [19, 74, 46, 4, 75, 47], [28, 50, 22, 6, 51, 23], [33, 46, 16, 4, 47, 17], [8, 152, 122, 4, 153, 123], [22, 73, 45, 3, 74, 46], [8, 53, 23, 26, 54, 24], [12, 45, 15, 28, 46, 16], [3, 147, 117, 10, 148, 118], [3, 73, 45, 23, 74, 46], [4, 54, 24, 31, 55, 25], [11, 45, 15, 31, 46, 16], [7, 146, 116, 7, 147, 117], [21, 73, 45, 7, 74, 46], [1, 53, 23, 37, 54, 24], [19, 45, 15, 26, 46, 16], [5, 145, 115, 10, 146, 116], [19, 75, 47, 10, 76, 48], [15, 54, 24, 25, 55, 25], [23, 45, 15, 25, 46, 16], [13, 145, 115, 3, 146, 116], [2, 74, 46, 29, 75, 47], [42, 54, 24, 1, 55, 25], [23, 45, 15, 28, 46, 16], [17, 145, 115], [10, 74, 46, 23, 75, 47], [10, 54, 24, 35, 55, 25], [19, 45, 15, 35, 46, 16], [17, 145, 115, 1, 146, 116], [14, 74, 46, 21, 75, 47], [29, 54, 24, 19, 55, 25], [11, 45, 15, 46, 46, 16], [13, 145, 115, 6, 146, 116], [14, 74, 46, 23, 75, 47], [44, 54, 24, 7, 55, 25], [59, 46, 16, 1, 47, 17], [12, 151, 121, 7, 152, 122], [12, 75, 47, 26, 76, 48], [39, 54, 24, 14, 55, 25], [22, 45, 15, 41, 46, 16], [6, 151, 121, 14, 152, 122], [6, 75, 47, 34, 76, 48], [46, 54, 24, 10, 55, 25], [2, 45, 15, 64, 46, 16], [17, 152, 122, 4, 153, 123], [29, 74, 46, 14, 75, 47], [49, 54, 24, 10, 55, 25], [24, 45, 15, 46, 46, 16], [4, 152, 122, 18, 153, 123], [13, 74, 46, 32, 75, 47], [48, 54, 24, 14, 55, 25], [42, 45, 15, 32, 46, 16], [20, 147, 117, 4, 148, 118], [40, 75, 47, 7, 76, 48], [43, 54, 24, 22, 55, 25], [10, 45, 15, 67, 46, 16], [19, 148, 118, 6, 149, 119], [18, 75, 47, 31, 76, 48], [34, 54, 24, 34, 55, 25], [20, 45, 15, 61, 46, 16]]; QRRSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) {
        var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); if (rsBlock == undefined) { throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel); }
        var length = rsBlock.length / 3; var list = []; for (var i = 0; i < length; i++) { var count = rsBlock[i * 3 + 0]; var totalCount = rsBlock[i * 3 + 1]; var dataCount = rsBlock[i * 3 + 2]; for (var j = 0; j < count; j++) { list.push(new QRRSBlock(totalCount, dataCount)); } }
        return list;
    }; QRRSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) { switch (errorCorrectLevel) { case QRErrorCorrectLevel.L: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; case QRErrorCorrectLevel.M: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; case QRErrorCorrectLevel.Q: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; case QRErrorCorrectLevel.H: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; default: return undefined; } }; function QRBitBuffer() { this.buffer = []; this.length = 0; }
    QRBitBuffer.prototype = { get: function (index) { var bufIndex = Math.floor(index / 8); return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1; }, put: function (num, length) { for (var i = 0; i < length; i++) { this.putBit(((num >>> (length - i - 1)) & 1) == 1); } }, getLengthInBits: function () { return this.length; }, putBit: function (bit) {
        var bufIndex = Math.floor(this.length / 8); if (this.buffer.length <= bufIndex) { this.buffer.push(0); }
        if (bit) { this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)); }
        this.length++;
    }
    }; var QRCodeLimitLength = [[17, 14, 11, 7], [32, 26, 20, 14], [53, 42, 32, 24], [78, 62, 46, 34], [106, 84, 60, 44], [134, 106, 74, 58], [154, 122, 86, 64], [192, 152, 108, 84], [230, 180, 130, 98], [271, 213, 151, 119], [321, 251, 177, 137], [367, 287, 203, 155], [425, 331, 241, 177], [458, 362, 258, 194], [520, 412, 292, 220], [586, 450, 322, 250], [644, 504, 364, 280], [718, 560, 394, 310], [792, 624, 442, 338], [858, 666, 482, 382], [929, 711, 509, 403], [1003, 779, 565, 439], [1091, 857, 611, 461], [1171, 911, 661, 511], [1273, 997, 715, 535], [1367, 1059, 751, 593], [1465, 1125, 805, 625], [1528, 1190, 868, 658], [1628, 1264, 908, 698], [1732, 1370, 982, 742], [1840, 1452, 1030, 790], [1952, 1538, 1112, 842], [2068, 1628, 1168, 898], [2188, 1722, 1228, 958], [2303, 1809, 1283, 983], [2431, 1911, 1351, 1051], [2563, 1989, 1423, 1093], [2699, 2099, 1499, 1139], [2809, 2213, 1579, 1219], [2953, 2331, 1663, 1273]];

    function _isSupportCanvas() {
        return typeof CanvasRenderingContext2D != "undefined";
    }

    // android 2.x doesn't support Data-URI spec
    function _getAndroid() {
        var android = false;
        var sAgent = navigator.userAgent;

        if (/android/i.test(sAgent)) { // android
            android = true;
            var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i);

            if (aMat && aMat[1]) {
                android = parseFloat(aMat[1]);
            }
        }

        return android;
    }

    var svgDrawer = (function () {

        var Drawing = function (el, htOption) {
            this._el = el;
            this._htOption = htOption;
        };

        Drawing.prototype.draw = function (oQRCode) {
            var _htOption = this._htOption;
            var _el = this._el;
            var nCount = oQRCode.getModuleCount();
            var nWidth = Math.floor(_htOption.width / nCount);
            var nHeight = Math.floor(_htOption.height / nCount);

            this.clear();

            function makeSVG(tag, attrs) {
                var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
                for (var k in attrs)
                    if (attrs.hasOwnProperty(k)) el.setAttribute(k, attrs[k]);
                return el;
            }

            var svg = makeSVG("svg", { 'viewBox': '0 0 ' + String(nCount) + " " + String(nCount), 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight });
            svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
            _el.appendChild(svg);

            svg.appendChild(makeSVG("rect", { "fill": _htOption.colorLight, "width": "100%", "height": "100%" }));
            svg.appendChild(makeSVG("rect", { "fill": _htOption.colorDark, "width": "1", "height": "1", "id": "template" }));

            for (var row = 0; row < nCount; row++) {
                for (var col = 0; col < nCount; col++) {
                    if (oQRCode.isDark(row, col)) {
                        var child = makeSVG("use", { "x": String(col), "y": String(row) });
                        child.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template")
                        svg.appendChild(child);
                    }
                }
            }
        };
        Drawing.prototype.clear = function () {
            while (this._el.hasChildNodes())
                this._el.removeChild(this._el.lastChild);
        };
        return Drawing;
    })();

    var useSVG = document.documentElement.tagName.toLowerCase() === "svg";

    // Drawing in DOM by using Table tag
    var Drawing = useSVG ? svgDrawer : !_isSupportCanvas() ? (function () {
        var Drawing = function (el, htOption) {
            this._el = el;
            this._htOption = htOption;
        };

        /**
        * Draw the QRCode
        * 
        * @param {QRCode} oQRCode
        */
        Drawing.prototype.draw = function (oQRCode) {
            var _htOption = this._htOption;
            var _el = this._el;
            var nCount = oQRCode.getModuleCount();
            var nWidth = Math.floor(_htOption.width / nCount);
            var nHeight = Math.floor(_htOption.height / nCount);
            var aHTML = ['<table style="border:0;border-collapse:collapse;">'];

            for (var row = 0; row < nCount; row++) {
                aHTML.push('<tr>');

                for (var col = 0; col < nCount; col++) {
                    aHTML.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:' + nWidth + 'px;height:' + nHeight + 'px;background-color:' + (oQRCode.isDark(row, col) ? _htOption.colorDark : _htOption.colorLight) + ';"></td>');
                }

                aHTML.push('</tr>');
            }

            aHTML.push('</table>');
            _el.innerHTML = aHTML.join('');

            // Fix the margin values as real size.
            var elTable = _el.childNodes[0];
            var nLeftMarginTable = (_htOption.width - elTable.offsetWidth) / 2;
            var nTopMarginTable = (_htOption.height - elTable.offsetHeight) / 2;

            if (nLeftMarginTable > 0 && nTopMarginTable > 0) {
                elTable.style.margin = nTopMarginTable + "px " + nLeftMarginTable + "px";
            }
        };

        /**
        * Clear the QRCode
        */
        Drawing.prototype.clear = function () {
            this._el.innerHTML = '';
        };

        return Drawing;
    })() : (function () { // Drawing in Canvas
        function _onMakeImage() {
            this._elImage.src = this._elCanvas.toDataURL("image/png");
            this._elImage.style.display = "block";
            this._elCanvas.style.display = "none";
        }

        // Android 2.1 bug workaround
        // http://code.google.com/p/android/issues/detail?id=5141
        if (this._android && this._android <= 2.1) {
            var factor = 1 / window.devicePixelRatio;
            var drawImage = CanvasRenderingContext2D.prototype.drawImage;
            CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) {
                if (("nodeName" in image) && /img/i.test(image.nodeName)) {
                    for (var i = arguments.length - 1; i >= 1; i--) {
                        arguments[i] = arguments[i] * factor;
                    }
                } else if (typeof dw == "undefined") {
                    arguments[1] *= factor;
                    arguments[2] *= factor;
                    arguments[3] *= factor;
                    arguments[4] *= factor;
                }

                drawImage.apply(this, arguments);
            };
        }

        /**
        * Check whether the user's browser supports Data URI or not
        * 
        * @private
        * @param {Function} fSuccess Occurs if it supports Data URI
        * @param {Function} fFail Occurs if it doesn't support Data URI
        */
        function _safeSetDataURI(fSuccess, fFail) {
            var self = this;
            self._fFail = fFail;
            self._fSuccess = fSuccess;

            // Check it just once
            if (self._bSupportDataURI === null) {
                var el = document.createElement("img");
                var fOnError = function () {
                    self._bSupportDataURI = false;

                    if (self._fFail) {
                        self._fFail.call(self);
                    }
                };
                var fOnSuccess = function () {
                    self._bSupportDataURI = true;

                    if (self._fSuccess) {
                        self._fSuccess.call(self);
                    }
                };

                el.onabort = fOnError;
                el.onerror = fOnError;
                el.onload = fOnSuccess;
                el.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; // the Image contains 1px data.
                return;
            } else if (self._bSupportDataURI === true && self._fSuccess) {
                self._fSuccess.call(self);
            } else if (self._bSupportDataURI === false && self._fFail) {
                self._fFail.call(self);
            }
        };

        /**
        * Drawing QRCode by using canvas
        * 
        * @constructor
        * @param {HTMLElement} el
        * @param {Object} htOption QRCode Options 
        */
        var Drawing = function (el, htOption) {
            this._bIsPainted = false;
            this._android = _getAndroid();

            this._htOption = htOption;
            this._elCanvas = document.createElement("canvas");
            this._elCanvas.width = htOption.width;
            this._elCanvas.height = htOption.height;
            el.appendChild(this._elCanvas);
            this._el = el;
            this._oContext = this._elCanvas.getContext("2d");
            this._bIsPainted = false;
            this._elImage = document.createElement("img");
            this._elImage.alt = "Scan me!";
            this._elImage.style.display = "none";
            this._el.appendChild(this._elImage);
            this._bSupportDataURI = null;
        };

        /**
        * Draw the QRCode
        * 
        * @param {QRCode} oQRCode 
        */
        Drawing.prototype.draw = function (oQRCode) {
            var _elImage = this._elImage;
            var _oContext = this._oContext;
            var _htOption = this._htOption;

            var nCount = oQRCode.getModuleCount();
            var nWidth = _htOption.width / nCount;
            var nHeight = _htOption.height / nCount;
            var nRoundedWidth = Math.round(nWidth);
            var nRoundedHeight = Math.round(nHeight);

            _elImage.style.display = "none";
            this.clear();

            for (var row = 0; row < nCount; row++) {
                for (var col = 0; col < nCount; col++) {
                    var bIsDark = oQRCode.isDark(row, col);
                    var nLeft = col * nWidth;
                    var nTop = row * nHeight;
                    _oContext.strokeStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight;
                    _oContext.lineWidth = 1;
                    _oContext.fillStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight;
                    _oContext.fillRect(nLeft, nTop, nWidth, nHeight);

                    // 안티 앨리어싱 방지 처리
                    _oContext.strokeRect(
						Math.floor(nLeft) + 0.5,
						Math.floor(nTop) + 0.5,
						nRoundedWidth,
						nRoundedHeight
					);

                    _oContext.strokeRect(
						Math.ceil(nLeft) - 0.5,
						Math.ceil(nTop) - 0.5,
						nRoundedWidth,
						nRoundedHeight
					);
                }
            }

            this._bIsPainted = true;
        };

        /**
        * Make the image from Canvas if the browser supports Data URI.
        */
        Drawing.prototype.makeImage = function () {
            if (this._bIsPainted) {
                _safeSetDataURI.call(this, _onMakeImage);
            }
        };

        /**
        * Return whether the QRCode is painted or not
        * 
        * @return {Boolean}
        */
        Drawing.prototype.isPainted = function () {
            return this._bIsPainted;
        };

        /**
        * Clear the QRCode
        */
        Drawing.prototype.clear = function () {
            this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height);
            this._bIsPainted = false;
        };

        /**
        * @private
        * @param {Number} nNumber
        */
        Drawing.prototype.round = function (nNumber) {
            if (!nNumber) {
                return nNumber;
            }

            return Math.floor(nNumber * 1000) / 1000;
        };

        return Drawing;
    })();

    /**
    * Get the type by string length
    * 
    * @private
    * @param {String} sText
    * @param {Number} nCorrectLevel
    * @return {Number} type
    */
    function _getTypeNumber(sText, nCorrectLevel) {
        var nType = 1;
        var length = _getUTF8Length(sText);

        for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
            var nLimit = 0;

            switch (nCorrectLevel) {
                case QRErrorCorrectLevel.L:
                    nLimit = QRCodeLimitLength[i][0];
                    break;
                case QRErrorCorrectLevel.M:
                    nLimit = QRCodeLimitLength[i][1];
                    break;
                case QRErrorCorrectLevel.Q:
                    nLimit = QRCodeLimitLength[i][2];
                    break;
                case QRErrorCorrectLevel.H:
                    nLimit = QRCodeLimitLength[i][3];
                    break;
            }

            if (length <= nLimit) {
                break;
            } else {
                nType++;
            }
        }

        if (nType > QRCodeLimitLength.length) {
            throw new Error("Too long data");
        }

        return nType;
    }

    function _getUTF8Length(sText) {
        var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
        return replacedText.length + (replacedText.length != sText ? 3 : 0);
    }

    /**
    * @class QRCode
    * @constructor
    * @example 
    * new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie");
    *
    * @example
    * var oQRCode = new QRCode("test", {
    *    text : "http://naver.com",
    *    width : 128,
    *    height : 128
    * });
    * 
    * oQRCode.clear(); // Clear the QRCode.
    * oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode.
    *
    * @param {HTMLElement|String} el target element or 'id' attribute of element.
    * @param {Object|String} vOption
    * @param {String} vOption.text QRCode link data
    * @param {Number} [vOption.width=256]
    * @param {Number} [vOption.height=256]
    * @param {String} [vOption.colorDark="#000000"]
    * @param {String} [vOption.colorLight="#ffffff"]
    * @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H] 
    */
    QRCode = function (el, vOption) {
        this._htOption = {
            width: 256,
            height: 256,
            typeNumber: 4,
            colorDark: "#000000",
            colorLight: "#ffffff",
            correctLevel: QRErrorCorrectLevel.H
        };

        if (typeof vOption === 'string') {
            vOption = {
                text: vOption
            };
        }

        // Overwrites options
        if (vOption) {
            for (var i in vOption) {
                this._htOption[i] = vOption[i];
            }
        }

        if (typeof el == "string") {
            el = document.getElementById(el);
        }

        if (this._htOption.useSVG) {
            Drawing = svgDrawer;
        }

        this._android = _getAndroid();
        this._el = el;
        this._oQRCode = null;
        this._oDrawing = new Drawing(this._el, this._htOption);

        if (this._htOption.text) {
            this.makeCode(this._htOption.text);
        }
    };

    /**
    * Make the QRCode
    * 
    * @param {String} sText link data
    */
    QRCode.prototype.makeCode = function (sText) {
        this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel);
        this._oQRCode.addData(sText);
        this._oQRCode.make();
        this._el.title = sText;
        this._oDrawing.draw(this._oQRCode);
        this.makeImage();
    };

    /**
    * Make the Image from Canvas element
    * - It occurs automatically
    * - Android below 3 doesn't support Data-URI spec.
    * 
    * @private
    */
    QRCode.prototype.makeImage = function () {
        if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) {
            this._oDrawing.makeImage();
        }
    };

    /**
    * Clear the QRCode
    */
    QRCode.prototype.clear = function () {
        this._oDrawing.clear();
    };

    /**
    * @name QRCode.CorrectLevel
    */
    QRCode.CorrectLevel = QRErrorCorrectLevel;
})(); ;
///<jscompress sourcefile="Selector.js" />
//#region 选择器区域

//var win = window;//  doc = document;
//window.U.Json_ = window.$; //记录命名控件 //全局使用  解决jquery覆盖我们的选择器的问题。

/*下面的写法会导致程序在window.onload之前执行,为什么要在window.onload之前执行,如果非要执行,能否把所有要做window.onload之前执行的整合在一个文件?并列明必须先执行的理由?*/

/*
选择器前言
好处:
1、简化项目的代码
2、当我对系统的ocument.getElementById  document.getElementsByTagName document.getElementsByClassName有奇异 觉得里面需要修改添加一些新的方法处理 可以统一处理
*/

//#region 创建元素
/*
*使用$$操作符简化编码长度。
*例:$$("div", { "style": { "cssText": "font-size:16px;float:left;line-height:33px;width:40%;margin:0px 0px 0px 15px;" }, "innerHTML": "文件名" }, Inner_J)
* @param   {string} 元素的类型tagName 例如:"div"
* @param   {object} 集合,类似  { "style": { "cssText": "font-size:16px;float:left;line-height:33px;width:40%;margin:0px 0px 0px 15px;" }, "innerHTML": "文件名" }
* @param   {element} 所要追加的父亲元素,把第二个参数作为孩子节点追加到第三个参数。par代表父亲元素
* @param   {element} 追加的位置,如果有此参数,则把创建的元素追加到此元素的前面。此元素必须为第三个参数的孩子节点。
*/
U.quickCreate = window.$$ = function (str, obj, parentel, child) { //创建基本元素元素
    var i, _element;
    //由于createDocumentFragment和createTextNode太长,可以通过简单的方式去创建
    var _obj = {
        "frag": "createDocumentFragment" //碎片元素
        //  "text": "createTextNode" //文本元素
    };
    //判断是否创建上面的元素方式
    if (_obj[str]) {
        _element = document[_obj[str]]();
    }
    //创建制定标签的元素
    else {
        _element = document.createElement(str);
    }
    //给元素添加属性
    if (obj) {
        U.selectEl(_element).addAttrArray(obj);
    }
    //如果存在父亲,则追加孩子节点。
    if (parentel) {
        //如果存在第四个参数,则追加到第四个参数的前面。否则,追加在最后面。
        if (child) {
            parentel.insertBefore(_element, child);
        }
        //追加到父亲元素的最后面
        else {
            parentel.appendChild(_element);
        }
    }
    //返回创建的元素
    return _element;
}

//#endregion

//#region 1473用的快速选择器 去除没有必要的功能 只保留简单的选择功能

/**
* 初始化编辑区域
*
* @param   {string} 选择 首先我们会定义3个获取元素的方法代替系统的 document.getElementById  document.getElementsByTagName document.getElementsByClassName
* @param   {元素} 在元素下面搜索符合参数一的所有孩子节点
例一、$("#U_MD_D_H");找名为U_MD_D_H唯一id。
例二、$("div", UDKF):在元素UDKF下面搜索所有div元素。
例三:$(".className", UDKF) 在元素UDKF下面找classname等于classname的元素。不建议用,性能太低。
*/
$ = U.selectEl = function (name, el) {
    //调用选择器的方法
    return new U.select(name, el);
}

/**
* 初始化编辑区域
*
* @param   {string} 选择的元素,例如"div"
* @param   {document} 搜索的层次
* 返回值:数组  [elment,elment,element]
*    var a=U.select("div.classname",body);
*    var b=U.select("input,a)
*/
U.select = function (selector, el) { //定义类
    //设置值
    this.length = 0; //选择元素的总长度
    this.context = el || document; //选择器的域(在哪个元素下面选,默认是document)
    //获取元素选择
    this.select(selector, el); //选择元素
}

U.select.EVENTS = [];  //元素绑定事件存储的地方

/**
* 这里是选择器的方法集合
*
*/
U.select.prototype = {//原型对象使用
    /**
    * 定义选择器构造器
    *
    * @param   {string} 选择特殊字符串 包含# & []
    * @param   {document} 搜索的层次
    */
    select: function (name, el) { //选择器选择
        var _selectel;
        //如果是字符串说明用户要通过选择器找到字符串
        if (U.UF.C.isString(name)) {
            var _r = name.substring(0, 1), //获取特殊字符 . # 或者 ""
                _n = name.substring(1, name.length), //获取标签名
                _doc = el || document; //去除特殊字符后

            //这里是判断获取
            try { //这里利用基础的选择器选取数据 
                switch (_r) {
                    case "#": //根据id获取 因为id获取只能通过全局搜索 但是由于项目中有存在克隆的情况 会出现id不唯一的情况
                        if (_doc == document && U.UF.S.EN.test(_n)) {
                            _selectel = document.getElementById(_n);
                        }
                        break;
                    case ".": //根据className获取
                        if (U.UF.S.EN.test(_n)) {
                            _selectel = _doc.getElementsByClassName(_n);
                        }
                        break;
                    case "*":
                        //如果后面有输入id,那么找所有的媒体文件
                        if (U.UF.S.EN.test(_n)) {
                            _selectel = document[_n]; //获取媒体文件
                            if (!_selectel) { //如果没有找到说明不兼容
                                if (U.UF.CI.getBrowser().browser == "msie") { //ie得到媒体文件的方法
                                    _selectel = document.getElementById(_n);
                                }
                                //非ie系列
                                else {
                                    _selectel = document.embeds[_n];
                                }
                            }
                        }
                        //否则就是直接找指定元素下面的所有元素
                        else {
                            _selectel = _doc.getElementsByTagName("*");
                        }
                        break;
                    default: //标签的获取 //获取指定的元素
                        if (U.UF.S.EN.test(name)) {
                            _selectel = _doc.getElementsByTagName(name); //除去特殊字符的处理
                        }
                        break;
                }
            }
            catch (e) {
            }
            //判断是否获取元素成功,如果上面简单的选择去不成功,那么就通过其他的选择器方案去获取
            if (_selectel == null) {
                _selectel = U.UF.CP.selectorElement(name, _doc); //其他选择的方式获取
            }
        }
        //如果用户第一个参数传的是元素,那么就直接设置
        else if (name) {
            _selectel = name;
        }
        //添加元素到this里面
        if (_selectel) {
            this.addElement(_selectel);
        }
        return this;
    },
    /**
    * 添加查找到的元素到this里
    *
    * @param   {elements} 选择的元素数组
    */
    addElement: function (els) {
        //把所有获取出来的元素转化成数组,以便下面循环添加 U.UF.C.isElement(els) || els.length == null
        if ((U.UF.C.isElement(els) || els.length == null) || els.toString() == "[object Window]") {
            els = [els];
        }
        //循环所有的元素,把元素设置到this里面,这样用户获取到的元素集就能通过this[0]或者this[id]去获取了
        for (var i = 0; i < els.length; i++) {
            //如果元素存在的处理
            this[i] = els[i];
            //如果元素有id,那么给返回值添加一个id的处理,以便返回值中有以id作为key的返回值
            if (els[i].id) {
                this[els[i].id] = els[i];
            }
            this.length++; //没添加一个那么选择的元素的长度多一个
        }
    },
    /**
    * 在选择好的元素下面继续搜索子元素
    *
    * @param   {string} 选择特殊字符串 包含# & []
    * @param   {number} 搜索的层次
    */
    find: function (name, item) { //获取元素的后代
        var i = item || 0, //由于选择选择出来的元素是数组,所以需要筛选出第几个需要获取子节点
            _length = item + 1 || this.length, //选择元素的长度
            _elements = new U.select(); //由于新选择了元素,那么实例化选择器
        for (; i < _length; i++) {
            _elements.select(name, this[i]); //重新选择添加处理
        }
        return _elements; //返回最后选择的结果
    },
    /**
    * 当前元素前一个兄弟节点
    *
    * @param   {string} 选择特殊字符串 包含# & []
    * @param   {number} 搜索的层次
    */
    prev: function (item) {
        var _selectel, //获取选择的元素
            _selects = [], //所有选择的元素
            i = item || 0, //由于选择选择出来的元素是数组,所以需要筛选出第几个需要获取子节点
            _length = item + 1 || this.length, //选择元素的长度
            _elements = new U.select(); //由于新选择了元素,那么实例化选择器
        //循环的去获取每个元素的上级元素
        for (; i < _length; i++) {
            _selectel = this[i];
            if (_selectel) {
                //用do while去过滤文本节点,只找元素节点
                do {
                    _selectel = _selectel.previousSibling;
                }
                while (_selectel && _selectel.nodeType !== 1)
            }
            //找到节点追加到数组里
            if (_selectel) {
                _selects.push(_selectel);
            }
        }
        //把元素添加到_elements里,并返回到前台
        _elements.addElement(_selects);
        return _elements;
    },

    /**
    * 当前元素之后第一个兄弟节点
    *
    * @param   {string} 选择特殊字符串 包含# & []
    * @param   {number} 搜索的层次
    */
    next: function (item) {
        var _selectel, //获取选择的元素
            _selects = [], //所有选择的元素
            i = item || 0, //由于选择选择出来的元素是数组,所以需要筛选出第几个需要获取子节点
            _length = item + 1 || this.length, //选择元素的长度
            _elements = new U.select(); //由于新选择了元素,那么实例化选择器
        //循环的去获取每个元素的上级元素
        for (; i < _length; i++) {
            _selectel = this[i];
            if (_selectel) {
                //用do while去过滤文本节点,只找元素节点
                do {
                    _selectel = _selectel.nextSibling;
                }
                while (_selectel && _selectel.nodeType !== 1)
            }
            //找到节点追加到数组里
            if (_selectel) {
                _selects.push(_selectel);
            }
        }

        //把元素添加到_elements里,并返回到前台
        _elements.addElement(_selects);
        return _elements;
    },

    /**
    * 获取所有的子元素
    *
    * @param   {number} 选择器结果里面的第几个
    */
    Nodes: function (item) {
        item = item || 0; //由于选择选择出来的元素是数组,所以需要筛选出第几个需要获取子节点
        //直接返回所有的子节点
        if (this[item]) {
            this[item].childNodes;
        }
        ;
    },
    /**
    * 获取所有的子元素
    *
    * @param   {number} 选择器结果里面的第几个
    */
    Child: function (item) {//获取有效元素孩子节点
        item = item || 0; //由于选择选择出来的元素是数组,所以需要筛选出第几个需要获取子节点
        //如果选择的元素存在则获取子节点 通过U.UF.EL.getChildrenNoText 可以把 #text节点过滤
        if (this[item]) {
            return U.UF.EL.getChildrenNoText(this[item].childNodes)
        }
    },
    /**
    * 如果没有参数,则是查找自己的父亲,如果有参数,则查找符合条件的祖先元素。
    * 如果UTF是数字n,则向上查找n层祖先。
    * 如果UTF是属性,则查找符合条件的属性。
    *
    * @param   {number} 选择器结果里面的第几个
    */
    Parent: function (obj) {//获取上级父亲层
        var _while,
            _istrue,
            _el = this[0];
        obj = obj || 1; //如果没有条件,那么就是默认选取上一层的父亲
        if (U.UF.C.isNumber(obj)) {
            for (i = 0; i < obj; i++) {
                if (_el) { //判断是否有选取
                    _el = _el.parentNode;
                }
            }
        }
        else {
            //循环的向上寻找制定条件的元素,最大不超过document层
            _while: while (_el && _el != document) {
                _istrue = true;
                //循环判断条件是否匹配
                for (i in obj) {
                    //如果条件匹配
                    if (obj[i] != _el[i] && (!_el.getAttribute || _el.getAttribute(i) != obj[i])) {
                        _istrue = false;
                        break;
                    }
                }
                //如果全部条件符合,那么直接跳出
                if (_istrue) {
                    break _while;
                }
                //继续向上找
                else {
                    _el = _el.parentNode;
                }
            }
        }
        //返回找到的祖先层
        return _el;
    },

    /**
    * 获取所有的子元素
    *
    * @param   {number} 选择器结果里面的第几个
    */
    childs: function (item) {//获取孩子节点
        return new U.select(this.Child(item));
    },
    /**
    * 如果没有参数,则是查找自己的父亲,如果有参数,则查找符合条件的祖先元素。
    * 如果UTF是数字n,则向上查找n层祖先。
    * 如果UTF是属性,则查找符合条件的属性。
    *
    * @param   {number} 选择器结果里面的第几个
    */
    parentElement: function (obj, item) {//获取父亲节点
        return new U.select(this.Parent(obj, item));
    },
    /**
    * 克隆元素
    *
    * @param   {boolean}    设置为 true,如果您需要克隆节点及其属性,以及后代, 设置为 false,如果您只需要克隆节点及其后代
    * @param   {number} 选择器结果里面的第几个
    */
    clone: function (deep, item) { //克隆元素 UDOD, UDID, USE
        var i = item || 0,  //item 基本没有用
            _returnarr = [], //返回的数据
            _length = i + 1 || this.length; //克隆元素的长度
        //循环克隆放入_returnarr里
        for (; i < _length; i++) {
            _returnarr.push(this[i].cloneNode(deep));
        }
        //返回选择器
        return new U.select(_returnarr);
    },
    /**
    * 把元素添加到制定的父亲层
    *
    * @param   {element} 添加到哪个父亲层
    * @param   {number} 选择器结果里面的第几个
    * @param   {element} 添加到哪个元素的上面
    */
    appendTo: function (parentel, item, childel) {//添加元素到制定的位置
        var i = item || 0, //选择器结果里面的第几个
            _length = item + 1 || this.length; //插入元素的长度
        //循环条件元素
        for (; i < _length; i++) {
            //如果有子元素,就添加到这个子元素的前面
            if (childel) {
                parentel.insertBefore(this[i], childel);
            }
            //添加到最后面
            else {
                parentel.appendChild(this[i]);
            }
        }
        return this;
    },
    /**
    * 添加子元素
    *
    * @param   {element} 需要追加的元素
    * @param   {number} 选择器结果里面的第几个
    * @param   {element} 添加到哪个元素的上面
    */
    append: function (el, item, childel) {//插入元素
        item = item || 0; //选择器结果里面的第几个
        //如果有子元素,就添加到这个子元素的前面
        if (childel) {
            this[item].insertBefore(el, childel);
        }
        //添加到最后面
        else {
            this[item].appendChild(el);
        }
        return this;
    },
    /**
    * 移除元素
    *
    * @param   {boolean}    设置为 true,如果您需要克隆节点及其属性,以及后代, 设置为 false,如果您只需要克隆节点及其后代
    * @param   {number} 选择器结果里面的第几个
    */
    remove: function (item) {
        var i = item || 0, //选择器结果里面的第几个
            _length = item != null ? item + 1 : this.length; //移除的数量
        //循环移除
        for (; i < _length; i++) {
            //判断是否有上一级
            if (this[i] && this[i].parentNode) {
                this[i].parentNode.removeChild(this[i]); //移除
            }
        }
        return this;
    },
    /**
    * 元素居中
    *
    * @param   {number} 选择器结果里面的第几个
    */
    Center: function (item) { //元素居中
        var i = item || 0,  //选择器结果里面的第几个
            _length = item + 1 || this.length; //居中弹出的数量
        //循环弹出处理
        for (; i < _length; i++) {
            U.UF.F.windowTopCenter(this[i]); //居中弹出
        }
        return this;
    },
    /**
    * 返回元素的大小和位置
    *
    * @param   {number} 选择器结果里面的第几个
    */
    getElementInfo: function (item) {
        return U.UF.EL.getElementInfo(this[item || 0]);
    },

    /**
    * 返回元素的大小和位置
    *
    * 设置单个Css属性传参说明
    * @obj     {string} 必填 css属性名
    * @value   {string} 必填 css属性对应的值
    * @item    {number} 选填 选择器结果里面的第几个
    *
    * 设置多个Css属性传参说明
    * @obj     {string} 必填 需设置的cssjson
    *    形如:{width : '100px', height: '100px', 'backgroud-color': 'red'}
    * @value   {null}   占位传参  null
    * @item    {number} 选填 选择器结果里面的第几个
    */
    css: function (obj, value, item) {//获取指定的css值
        var i = item || 0, //选择第几个
            _length = item + 1 || this.length, //长度
            _isobject = U.UF.C.isObject(obj);

        //如果是object,那么第二个参数就是item 所以这里的 value = item
        if (_isobject) {
            this.addAttrArray({ "style": obj }, value);
        }
        //如果第一个参数是strig类型那么value需要有值,如果有值那么就是设置,否则是获取css
        else if (value != null) {
            //循环的设置值
            for (i; i < _length; i++) {
                obj = U.UF.EL.styleConversion(obj); //由于用户这边会穿 text-align 这样的值 但是在css里面 该值为 textAlign改成了大写
                try {
                    this[i].style[obj] = value;
                } catch (e) { }
            }
        }
        //获取css
        else {
            return U.UF.EL.getStyle(this[i], obj);
        }
        return this;
    },
    /**
    * 添加classname
    *
    * @param   {string} 移除的classname
    */
    addClass: function (classname, item) { //添加Class
        var i = item || 0, //选择第几个
            _length = item + 1 || this.length; //长度
        //循环给元素添加class值
        for (; i < _length; i++) {
            U.UF.EL.addClass(this[i], classname);
        }
        return this;
    },
    /**
    * 移除classname
    *
    * @param   {string} 移除的classname
    */
    removeClass: function (classname, item) {//移除制定的class
        var i = item || 0, //选择第几个
            _length = item + 1 || this.length; //长度
        //循环给元素移除classname
        for (; i < _length; i++) {
            U.UF.EL.removeClass(this[i], classname);
        }
        return this;
    },
    /**
    * 判断元素是否有制定的class
    *
    * @param   {string} classname
    */
    hasClass: function (classname, item) {
        item = item || 0;
        return U.UF.EL.isHasClass(this[item], classname);
    },
    /**
    * 判断元素是否有制定的class
    *
    * @param   {string} classname
    */
    attr: function (obj, value, item) { //添加属性
        var j,
            i, //选择第几个
            _length, //长度
            _isobject = U.UF.C.isObject(obj); //判断元素是否为对象

        //如果是object,那么第二个参数就是item 所以这里的 value = item
        if (_isobject) {
            i = value || 0; //选择第几个
            _length = value + 1 || this.length; //长度
            //循环所有的元素添加至
            for (; i < _length; i++) {
                for (j in obj) {
                    U.UF.EL.addAttributes(this[i], j, obj[j]); //给元素添加属性
                }
            }
        }
        //如果第一个参数是strig类型那么value需要有值,如果有值那么就是设置,否则是获取css
        else if (value != null) {
            i = item || 0; //选择第几个
            _length = item + 1 || this.length; //长度
            //循环的设置值
            for (i; i < _length; i++) {
                U.UF.EL.addAttributes(this[i], obj, value); //给元素添加属性
            }
        }
        //获取属性,
        else {
            return this[item || 0].getAttribute(obj);
        }
        return this;
    },
    /**
    * 移除属性
    *
    * @param   {string} classname
    */
    rmAttr: function (name, item) { //移除属性
        U.UF.EL.delAttributes(this[item || 0], name); //移除元素
        return this;
    },
    /**
    * 添加属性
    *
    * @param   {string} classname
    */
    addAttrArray: function (obj, item) {//赋值区域
        var j, k,
            _newcsstext,
            _csstype,
            _csstext = "", //csstext
            i = item || 0, //选择第几个
            _length = item + 1 || this.length; //长度
        //循环的处理每个元素赋值
        for (; i < _length; i++) {
            //循环所有的属性
            for (j in obj) {
                //css的添加方式
                if (j == "style") {
                    _csstext = "";
                    _newcsstext = obj[j]["cssText"];
                    for (k in obj[j]) {
                        _csstype = U.UF.EL.styleConversion(k, true); //把所有的cssText转成css-text,因为css在拼接的时候是以这种形式
                        //cssText的设置方式,添加一份新的csstext
                        if (_csstype == "css-text") {
                            continue;
                        }
                        //如果是其他普通样式的添加,那么就拼接
                        else if (k in this[i][j]) {
                            _csstext += _csstype + ":" + obj[j][k] + ";";
                        }
                        //自定义属性的设置,情况比较少,但是在做兼容方案的时候可能会用到
                        else {
                            this[i][j][k] = obj[j][k];
                        }
                    }
                    //如果需要设置cssText的处理
                    if (_newcsstext) {
                        _csstext = this[i][j]["cssText"] + ";" + _newcsstext + ";" + _csstext;
                    }
                    //如果是undefined或者是null这样不设置值的处理
                    else if (_newcsstext !== "") {
                        _csstext = this[i][j]["cssText"] + ";" + _csstext;
                    }
                    this[i][j]["cssText"] = _csstext;
                }
                //出css以外的添加方式 如 onclick事件赋值 classname赋值
                else {
                    //如果是事件类型的,又是字符串类型,那么这里把它转化成函数
                    if (j.indexOf("on") == 0 && U.UF.C.isString(obj[j])) {
                        this[i][j] = new Function(obj[j]); //字符串转化成function
                        continue;
                    }
                    //&& "string".indexOf(U.UF.C.getType((_UVE = UDE[j]))) > -1
                    //如果是字符串,同时又是系统属性,那么通过setAttribute的方式设置属性,该方式设置属性可以让属性在网页调试模式下看到如<div kk="kk"> kk为自定义属性
                    else if (U.UF.C.isString(obj[j]) && U.UF.EL.isCustomAttributes(this[i], j)) {
                        //由于低版本的浏览器会报错,这里用try catch
                        try {
                            this[i].setAttribute(j, obj[j]);
                        }
                        catch (e) {
                        }
                    }
                    try {
                        this[i][j] = obj[j];
                    }
                    catch (e) { }
                }
            }
        }
        return this;
    },
    /**
    * 隐藏元素
    *
    * @param   {string} classname
    */
    hide: function (item) {
        this.css({ "display": "none" }, item);
    },
    /**
    * 显示元素
    *
    * @param   {string} classname
    */
    show: function (item) { //显示元素
        this.css({ "display": "block" }, item);
    },
    /**
    * 获取长度
    *
    */
    width: function () {
        return U.UF.EL.getElementRealWidth(this[0]);
    },
    /**
    * 获取长度
    *
    */
    height: function () {
        return U.UF.EL.getElementRealHeight(this[0]);
    },
    /**
    * 鼠标移入的时候触发,由于onmouseover会出发多次 这里做兼容
    *
    * @param   {string} classname
    */
    mouseenter: function (cb, item) { //enter事件
        //设置移入函数
        this.addAttrArray({
            "onmouseover": function () {
                U.UF.EV.stopBubbleMouseOutOrOver(this, cb); //判断用户移入的时候出发元素,进行判断元素是否移入
            }
        }, item);
        return this;
    },
    /**
    * 鼠标移出的时候触发,由于onmouseout会出发多次 这里做兼容
    *
    * @param   {string} classname
    */
    mouseleave: function (cb, item) { //leave事件
        //设置移入函数
        this.addAttrArray({
            "onmouseout": function () {
                U.UF.EV.stopBubbleMouseOutOrOver(this, cb); //判断用户移入的时候出发元素,进行判断元素是否移入
            }
        }, item);
        return this;
    },
    /**
    * 鼠标移出的时候触发,由于onmouseout会出发多次 这里做兼容
    *
    * @param   {string} classname
    */
    gt: function (item) { //索引大于的元素
        var i = item,  //item 基本没有用
            _returnarr = [], //返回的数据
            _elements = new U.select(); //由于重新筛选数据,那么需要新建一个选择器
        //循环筛选元素
        for (; i < this.length; i++) {
            _returnarr.push(this[i]);
        }
        //循环添加到this里面
        _elements.addElement(_returnarr);
        return _elements;
    },
    /**
    * 鼠标移出的时候触发,由于onmouseout会出发多次 这里做兼容
    *
    * @param   {string} classname
    */
    lt: function (item) {
        var i = 0,  //item 基本没有用
            _returnarr = []; //返回的数据

        //循环筛选元素
        for (; i < item; i++) {
            _returnarr.push(this[i]);
        }
        //循环添加到this里面
        return new U.select(_returnarr); //由于重新筛选数据,那么需要新建一个选择器
    },

    /**
    * 元素事件绑定
    *
    * @param   {string} classname
    */
    bind: function (obj, value, item) {
        var j,
            i, //选择第几个
            _length, //长度
            _isobject = U.UF.C.isObject(obj); //判断元素是否为对象
        //如果是object,那么第二个参数就是item 所以这里的 value = item
        if (_isobject) {
            i = value || 0; //选择第几个
            _length = value + 1 || this.length; //长度
            //循环所有的元素添加至
            for (; i < _length; i++) {
                for (j in obj) {
                    U.UF.EV.addElementEvent(j, this[i], obj[j]); //添加事件绑定
                    //添加事件
                    U.select.EVENTS.push({
                        element: this[i], //绑定事件
                        event: j, //事件
                        fun: obj[j] //函数
                    });
                }
            }
        }
        //如果第一个参数是strig类型那么value需要有值,如果有值那么就是设置,否则是获取css
        else if (value != null) {
            i = item || 0; //选择第几个
            _length = item + 1 || this.length; //长度
            //循环的设置值
            for (i; i < _length; i++) {
                U.UF.EV.addElementEvent(obj, this[i], value); //添加事件绑定
                //添加事件
                U.select.EVENTS.push({
                    element: this[i], //绑定事件
                    event: obj, //事件
                    fun: value //函数
                });
            }
        }
        return this;
    },
    /**
    * 元素解除事件绑定
    *
    * @param   {string} classname
    */
    unbind: function (obj, value, item) { //事件绑定取消
        var j,
            i, //选择第几个
            k,
            _length, //长度
            _isobject = U.UF.C.isObject(obj); //判断元素是否为对象
        //如果是object,那么第二个参数就是item 所以这里的 value = item
        if (_isobject) {
            i = value || 0; //选择第几个
            _length = value + 1 || this.length; //长度
            //循环所有的元素添加至
            for (; i < _length; i++) {
                for (j in obj) {
                    U.UF.EV.delElementEvent(j, this[i], obj[j]); //删除事件绑定
                    for (k = 0; k < U.select.EVENTS.length; k++) {
                        if (U.select.EVENTS[k].element == this[i] && U.select.EVENTS[k].event == j && U.select.EVENTS[k].fun == obj[j]) {
                            U.select.EVENTS.splice(k, 1);
                            k--;
                        }
                    }
                }
            }
        }
        //如果第一个参数是strig类型那么value需要有值,如果有值那么就是设置,否则是获取css
        else if (obj != null) {
            i = item || 0; //选择第几个
            _length = item + 1 || this.length; //长度
            //循环的设置值
            for (i; i < _length; i++) {
                for (k = 0; k < U.select.EVENTS.length; k++) {
                    if (U.select.EVENTS[k].element == this[i] &&
                        U.select.EVENTS[k].event == obj &&
                        (value == null || U.select.EVENTS[k].fun == value)) {
                        U.UF.EV.delElementEvent(obj, this[i], U.select.EVENTS[k].fun); //添加事件绑定
                        U.select.EVENTS.splice(k, 1);
                        k--;
                    }
                }
            }
        }
        //如果没有传key和value去移除,那么就移除元素所有绑定的事件
        else {
            i = item || 0; //选择第几个
            _length = item + 1 || this.length; //长度
            for (i; i < _length; i++) {
                for (k = 0; k < U.select.EVENTS.length; k++) {
                    if (U.select.EVENTS[k].element == this[i]) {
                        U.UF.EV.delElementEvent(U.select.EVENTS[k].event, this[i], U.select.EVENTS[k].fun); //添加事件绑定
                        U.select.EVENTS.splice(k, 1);
                        k--;
                    }
                }
            }
        }
        return this;
    }
}


//#endregion
;
///<jscompress sourcefile="Type.js" />
/* 
一、此js主要扩展了String,Number,Array,Object,Guid,json,Date等七种数据类型,还有一些html5的数据类型,但暂未使用,此js需要立即执行的区域比较多。
没有对以下数据类型进行扩展 function Boolean null undefined。
二、此js包含了正则处理
*/
Namespace.register("U.UF.S");

//#region 正则方法区域

U.UF.S.browser = /(msie|firefox|chrome|ipad|iphone|safari|opera|version|rv).*?([\d.]+)/; //区分浏览器正则
U.UF.S.Event = /\[object (Keyboard|Mouse|Focus|Wheel|Composition|Storage|MS|)Event(Obj|)\]/; //判断是否为event
U.UF.S.Guid = /^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$/; //判断是否为Guid
U.UF.S.English = /^[A-Za-z]+$/; //是否为英文
U.UF.S.RNum = /\d+/g; //数字浮点等
U.UF.S.Number = /^\d+$/; //整数 
U.UF.S.Num = /^(-?\d+)(\.\d+)?$/; //浮点
U.UF.S.EN = /^([a-zA-Z0-9_\-]+)$/; //css样式名规则
U.UF.S.Url = /^\w+\:\/\/([\w+]).*/; //是否是有效链接
U.UF.S.FileName = /^([a-zA-Z0-9\u4e00-\u9fa5\s\._-]+)$/; //文件名判断
U.UF.S.ZWFileName = /^[0-9a-zA-Z\u4e00-\u9fa5\._-]{1,40}\\*$/; //文件名判断
U.UF.S.PBrief = /^.{0,100}$/; //判断是否为有效的签名
U.UF.S.FFZF = /^(\w|-|[\u4E00-\u9FA5])*$/; //中文字符下划线
U.UF.S.ChineseIdCard = /\d{17}[\d|X]|\d{15}/; //身份证
U.UF.S.TelephoneNumber = /^1[0-9]{10}$/; //电话号码
U.UF.S.Email = /^\w+([_+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; //邮箱
U.UF.S.TrueName = /^[\u4e00-\u9fa5]{1,20}$|^[a-zA-Z]{1,20}$/; //真实姓名
U.UF.S.UserName = /^\S{1,25}$/; //用户名
U.UF.S.NickName = /^[0-9a-zA-Z\u4e00-\u9fa5_-]{1,40}\\*$/; //昵称
U.UF.S.PassWord = /^[^\u4E00-\u9FA5\uF900-\uFA2D]{6,20}$/; //密码
U.UF.S.Visa = /^[45]\d{15}$/; //银行卡号
U.UF.S.rgb = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/ //rgb颜色判断

//#endregion

//#region 字符串处理
//---------------------------------- 字符串处理-------------------------------------
U.UF.C.String = {
    //场景:制作编辑器word,excel,txt时,把符号"'"转义成"\'",把符号"""转义成"\"".
    //作用,把符号"'"转义成"\'",把'张三'存入数据库,会报错,符号'''会在存储过程执行时报错,此时需要把"'"转成"\'",转换后的结果是"\'张三\'"
    //例:exec 存储过程 ''param'',转义为exec 存储过程 '\'param\''
    //把符号"""转义成"\"",把"张三"存入数据库,会报错,符号'"'会在存储过程执行时报错,此时需要把"""转成"\"",转换后的结果是"\"张三\""
    //例:exec 存储过程 ""param"",转义为exec 存储过程 "\"param\""
    escapeQuotes: function () {
        return this.replace(/'/ig, "''").replace(/"/ig, "\\\""); //字符串的形式输出
    },
    unEscapeQuotes: function () {
        return this.replace(/\\'/ig, '\'').replace(/\\"/ig, "\""); //字符串的形式输出
    },
    count: function () { //获取字符串长度
        return this.substrU(); //调用SubstrU() 获取字符串长度
    },
    //截取字符串在制定的长度内
    substrU: function (start, end) {
        var i, _UTF, _num = 0, _UMS = "";
        if (end == null && start != null) { end = start, start = 0 }; //参数只有一个的情况 start=0起点设置0 end=start把start当做截取字符串的终点
        _UTF = (start == null && end == null); //没有参数情况 _UTF=true
        for (i = 0; i < this.length; i++) {
            _num += this.charCodeAt(i) < 255 ? 1 : 2; //非常规字符判断长度为2 常规则1
            if (_num < start) { continue; } //当前长度小于起点则 continue
            if (_num <= end || _UTF) {//当前长度小于 终点
                _UMS += this.charAt(i); //获取字符串的第i个
                continue;
            }
            break; //不符合if时 break
        }
        return (_UTF ? _num : _UMS); //判断参数是否为空 为空返回长度 否则返回截取的字符串
    },
    //jsstring: function () { //json string
    //    return this.replace(/\r\n/g, "\\r\\n").replace(/\n/g, "\\n").replace(/\"/g, "\\\""); //把 \r\n转成 \\r\\n   \n转成\\n     \"转成\\\"
    //},
    //SubstrN: function (UN) { //判断是否在指定的长度内,
    //    return this.substrU(0, UN) == this; //用SubstrU截取0-UN的字符串 判断是否等于原字符串
    //},
    isStrNull: function () { //判断是否为空字符串
        return this.trim() == ""; //用trim 去除所有空白字符再判断是否等于 ""
    },
    //文本换行替换成页面换行,把\r\n 换成<br/>
    replaceRnToBr: function () {
        return this.replace(/\r\n/g, "<br />"); //把\r\n 换成<br/>
    },
    //成页面换行替换成文本换行,把<br/>换成\r\n
    replaceBrToRn: function () {
        return this.replace(/<(BR)[^<>]*>/ig, "\r\n"); // 把<br/>换成\r\n
    },
    removeP: function () { //去除P标签
        return this.replace(/<(p)[^<>]*>/ig, ""); //把<p></p> 去掉
    },
    removeBr: function () { //去除BR标签
        return this.replace(/<(BR)[^<>]*>/ig, ""); //把<br /> 去掉
    },
    removeRn: function () { //去除\r\n标签
        return this.replace(/\r\n/g, ""); //把\r\n 去掉
    },
    replaceBrAndBlank: function () { //把<br />转换为 \r\n并把空格"&nbsp"转换为"",应用场景在哪里?
        return this.replaceBrToRn().replace(/&nbsp;/g, '');
    },
    //判断用户是否在div可编辑区域里面输入了内容。
    isHtmlNull: function () { //移除<br />标签,移除P标签,去除所有空格。当用户发帖时需要判断用户是否输入了文字图片,可以用此函数判断用户是否输入了内容。在div可编辑时需要用此函数。
        return this.removeBr().removeP().trim() != ""; //
    },
    //把字符串中的&lt  &gt 分别转换成 < >
    replaceLtAndGt: function () {
        return this.replace(/&lt;/g, "<").replace(/&gt;/g, ">"); //所有&lt  &gt 分别转换成 < >
    },
    //把字符串中的 < >分别转换成&lt  &gt 
    replaceAngleBrackets: function () { //把字符串中的 < >分别转换成&lt  &gt 
        return this.replace(/</g, "&lt;").replace(/>/g, "&gt;"); //所有&lt  &gt 分别转换成 < >
    },
    //应用:从数据库取出的html代码会直接显示在页面中,为了让js,css等文字以文字的形式显示,而不是植入到页面中不显示,所以需要转义。
    //HTML字符转化为ASCLL码.把字符串中的 < >分别转换成&lt  &gt ,把"'"转换为"&#39;",把"""转换为"&quot;",把
    //注释:/&(?!#?[a-zA-Z0-9]+;)/g, "&amp;"暂时不知道什么意思。
    replaceHtmlSign: function () {
        return this.replace(/&(?!#?[a-zA-Z0-9]+;)/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&#39;").replace(/"/g, "&quot;");
    },
    replaceDoubleToAngleBrackets: function () { //html字符可输出
        return this.replace(/\《/g, "<").replace(/\》/g, ">"); //所有《》转换为<>
    },
    replaceAngleToDoubleBrackets: function () {//中文括号
        return this.replace(/\</g, "《").replace(/\>/g, "》"); // 所有<>转换为《》
    },
    trim: String.prototype.trim || function (str) {//去除所有空格,用于发帖时标题内容是否为空的判断,创建文件夹时输入文件夹名时的判断。
        return this.replace(/\ |\  |\s+|\n|\r|\t/g, str || ""); //去除空白符号、\t、\s、\r、\n
    },
    lTrim: function () { //去除左边空格
        return this.replace(/(^\s*)/g, "");
    },
    rTrim: function () { //去除右边边空格
        return this.replace(/(\s*$)/g, '');
    },
    addPreSpace: function (n) { //字符串前面追加n个空格,用于IDE编辑器环境前面空四格
        var i, k = "";
        for (i = 0; i < n; i++)
            k += " ";
        return k + this;
    },
    insertString: function (str, n) { //指定位置插入字符串
        //调用substr截取字符串 加上插入的字符  再加上 把原字符串删除前UN个字符的字符串
        var _pre = this.substr(0, n);
        var _back = this.substr(n, this.length);
        return _pre + str + _back;
    },
    //指定位置插入省略号, 常见于文章标题过长、文件夹名称过长,在显示时后面的字符以省略号代替
    addEllipsis: function (n) { //省略号
        var _str = this.substrU(0, n); //调用SubstrU 截取字符串
        if (_str != this) {
            _str = _str + "...";
        }
        //当修改String的原型时,会把字符串string替换为object的str,所以需要用valueOf()方法转换为字符串的string.  Object对象的格式类似 String {"asdasd"} 
        return _str.valueOf(); //判断_str是否为原字符串 不是的话返回_str加上...
    },
    //字符串转化成number
    toInt: function () {
        var _UTV = this.valueOf(), _UMS = _UTV.match(/^(-|\+)?\d+/g);
        return _UMS && _UMS.length == 1 ? Number(_UMS[0]) : _UTV;
    },
    //把原字符串source换成目标字符串target
    replaceStr: function (source, target) {
        return this.replace(new RegExp(source, "gm"), target); //把原字符串source换成目标字符串target
    },
    parseJSON: function () { //string 转 json对象
        var _obj = null, _str = this;
        try {
            _obj = eval("0,(" + _str + ")");
        } catch (e) { }
        return _obj == null ? _str.valueOf() : _obj;
    },
    capitalizeFirstLetter: function () { //首字母大写
        return this.replace(/\b(\w)|\s(\w)/g, function (UAE) { return UAE.toUpperCase(); });
    },
    //回车换行替换成换行 并返回按照\n拆分出的数组
    SplitRN: function () {
        return this.replace(/\r\n/g, "\n").split("\n"); //把\r\n替换成\n 并且根据\n把字符串分成数组
    },
    //根据符号"<",">"把html字符串拆分成数组,适合于IDE编辑器
    ////增加一个拆分html编码为字符串数组的操作,用于编辑器的换行,定义到主项目中
    //拆分HTML编码,适合于编辑器,不止是拆分html编码,同时还需要把中间的文字提出出来,例如javascript代码,div中间的文字等。
    //    SplitAngleBrackets: function () {
    //        var i, s, a = [];
    //        for (i = 0; i < this.length; i++) {
    //            if (this[i] == "<") {
    //                s = i;
    //            }
    //            if (this[i] == ">") {
    //                a.push(this.substring(s, i + 1));
    //            }
    //        };
    //        return a;
    //    },
    //根据符号"<",">"把html字符串拆分成数组,适合于IDE编辑器
    ////增加一个拆分html编码为字符串数组的操作,用于编辑器的换行,定义到主项目中
    //拆分HTML编码,适合于编辑器,不止是拆分html编码,同时还需要把中间的文字提出出来,例如javascript代码,div中间的文字等。
    SplitAngleBrackets: function () {
        return this.match(/(<(.[^>]*)>)|((|>)[^\<]*[^\<^\s])/g);
    },
    //过滤html标签留下纯文本,不保留任何格式
    htmlToText: function () { //过滤HTML标签留下纯文本
        return String(this).replace(/(<(.[^>]*)>)/g, "");
    },
    //过滤html标签留下纯文本,但保留换行符号
    htmlToTextRn: function () {
        return this.replace(/(<(.[^>]*)>)/g, function (str) {
            return (/(<\/(div|DIV|p|P)([|^>]*)>)|<(BR)[^<>]*>/ig.test(str)) ? "\r\n" : "";
        });
    },
    //获取body里面的html
    getBodyHtml: function () {
        try {
            return /<body[^>]*>([\s\S]*)<\/body>/.exec(String(this))[1].unEscapeQuotes();
        }
        catch (e) {
            return "";
        }
    }
};

//#endregion

//#region 数字Number

U.UF.C.Number = {
    //数字转换成货币的格式 100000 = 10,000
    formatMoney: function () {
        var _split; //
        var _arr = [];
        var _str = this.toString();
        while (_str) { //循环拆分
            _split = _str.length - 3;
            //unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
            _arr.unshift(_str.substr(_split < 0 ? 0 : _split));
            _str = _str.substr(0, _split);
        }
        return _arr.join(",");
    },
    //数字前面补零
    prefixInteger: function (n) {
        return (this < 10 ? "0" + this : this).valueOf(); //小于10 补零
        //Array(n)创建n位数组,join(0)以0作为分隔符, 
        return (Array(n).join(0) + this).slice(-n);
    },
    //把角度转换成弧度,
    toRadians: function () {  //返回圆弧率
        return this * Math.PI / 180; //PI即圆周率,Math.PI/180*t是将t把角度转换成弧度.缺少应用场景
    }

};

//#endregion

//#region 数组处理

/** 
* 判断是否为数组,//ie10以下浏览器不支持Array.isArray。使用return Object.prototype.toString.call(arr) === "[object Array]";做兼容。U.UF.C.Array是为了添加Array的原型方法,而Array.isArray不是原型方法,所以没有放到U.UF.C.Array中。
*
* @param  {array} 需要判断的类型
* @returns {bool} 返回真假
*/
//判断是否为数组

Array.isArray = Array.isArray || function (arr) {
    return Object.prototype.toString.call(arr) === "[object Array]";
}

//数组初始化类
U.UF.C.Array = {
    /**
    * 判断有否有内容包含在该数组中的位置
    *
    * @param  {string、number} 需要查找的值indexOf
    * @returns {int} -1 >-1 -1 就是数组不存在 >-1就是位置
    */
    indexOf: Array.prototype.indexOf || function (val, startpoint) {
        var i = startpoint || 0,
            j;
        //循环数组,获取数组的值
        for (; i < this.length; i++) {
            //在数组中查找制定的值,如果值匹配数组中的其中一个,那么返回该数组所在的位置
            if (this[i] == val) {
                return i;
            }
        }
        //如果没有找到制定的位置,那么就直接返回-1
        return -1;
    },
    //对象object在数组中的位置
    //参数:object 形如{"name":"张三"}
    objIndexOf: function (obj) {
        var i,
            j,
            _isfind;
        for (i = 0; i < this.length; i++) {
            _isfind = false; //默认没有找到位置。

            //循环所有的obj里面的key和value,匹配所有的key和value都正确的,找到第一个匹配成功的位置
            for (j in obj) {
                //根据key匹配了指定的值,那么设置为true
                if (this[i][j] == obj[j]) {
                    _isfind = true;
                }
                //如果根据key匹配指定的值错误,那么解决forin循环直接设置为false
                else {
                    _isfind = false;
                    break;
                }
            }
            //如果上面的obj判断全部正确,那么返回所在的位置,否则返回-1;
            if (_isfind) {
                return i;
            }
        }
        //如果没有找到制定的位置,那么就直接返回-1
        return -1;
    },

    /**
    * 移除数组里相同的值,  类似[element,elment,elment,element],或者[1,2,3,4,3,2],或者["张三","李四","张三","","王五"]
    *
    * @param  {string} 判断字段
    * @param  {string} 原数组
    * @returns 删除的原元素本身
    */
    unique: function () { //移除数组里相同的值
        //将数组的值作为对象的属性,通过对象的属性值来判断数组是否重复,若该项不重复则给对象对应属性值赋为true,便于之后的判断,并将数据项加入结果集中
        var result = [];
        var obj = {};
        for (var i = 0; i < this.length; i++) {
            if (!obj[this[i]]) {
                result.push(this[i]);
                obj[this[i]] = true;
            }
        }
        return result;
    },
    //以下几个函数是做浏览器兼容的,系统本身支持这些函数,但有些浏览器不支持,为了使所有浏览器都支持,则定义以下几个兼容函数。
    //方法对数组的每个元素执行一次提供的函数。
    //参数一:callback 为数组中每个元素执行的函数,该函数接收三个参数:currentValue(当前值) 数组中正在处理的当前元素。index(索引)数组中正在处理的当前元素的索引。arrayforEach()方法正在操作的数组。
    //参数二:可选参数。当执行回调 函数时用作this的值(参考对象)。
    forEach: Array.prototype.forEach || function (cb, thisArg) {//允许object和array使用
        var i = 0;
        var _length = this.length;
        while (i < _length) {
            cb.call(thisArg, this[i], i, this);
            i++;
        }
    },
    /**
    * 测试数组的所有元素是否都通过了指定函数的测试。
    *
    * @param  {function} 用来测试每个元素的函数。
    * @param  {Array} 执行 callback 时使用的 this 值。
    * @returns {boolean}
    */
    every: Array.prototype.every || function (cb, thisArg) {
        // return this.forEach(cb, UTI, "every");
        var i = 0, b;
        var _length = this.length;
        while (i < _length) {
            b = cb.call(thisArg, this[i], i, this);
            if (b == false) {
                return b;
            }
            i++;
        }
        return true;
    },
    /**
    * 方法测试数组中的某些元素是否通过由提供的函数实现的测试。
    *
    * @param  {function} 用来测试每个元素的回调函数
    * @param  {Array} 执行 callback 函数时 使用的this 值。
    * @returns {boolean}
    */
    some: Array.prototype.some || function (cb, thisArg) {
        var t = Object(this);
        var _len = t.length;
        for (var i = 0; i < _len; i++) {
            if (i in t && cb.call(thisArg, t[i], i, t))
            //为数组中的每一个元素执行一次 callback 函数,如果回调函数返回true的话,则some函数返回true。
                return true;
        }
        return false;
    },
    /**
    * 方法测试数组中的某些元素是否通过由提供的函数实现的测试。
    *
    * @param  {function} 生成新数组元素的函数,使用三个参数:
    currentValue callback 的第一个参数,数组中正在处理的当前元素。
    @param  {int}  callback 的第二个参数,数组中正在处理的当前元素的索引。
    @param  {Array} callback 的第三个参数,map 方法被调用的数组。
    * @param  {Array} 执行 callback 函数时 使用的this 值。
    * @returns {Array} 返回整合过后的新数组
    */
    map: Array.prototype.map || function (cb, thisArg) {
        /*var T, A, k;
        // 将O赋值为调用map方法的数组.
        var O = Object(this);
        //将len赋值为数组O的长度.
        var len = O.length;
        //如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
        if (thisArg) {
        T = thisArg;
        }
        //创建新数组A,长度为原数组O长度len
        A = new Array(len);
        //将k赋值为0
        k = 0;
        //当 k < len 时,执行循环.
        while (k < len) {
        var kValue, mappedValue;
        //遍历O,k为原数组索引
        if (k in O) {
        //kValue为索引k对应的值.
        kValue = O[k];
        // 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
        mappedValue = callback.call(T, kValue, k, O);
        // 返回值添加到新数组A中.
        A[k] = mappedValue;
        }
        // k自增1
        k++;
        }
        //返回新数组A
        return A;*/

        //定义自增量
        var i = 0;
        //定义数组长度
        var _length = this.length;
        //定义新的数组
        var _arr = [];

        //判断传入的cb必须是个'function',若不是返回类型错误提示
        if (typeof cb != "function")
            throw new TypeError();

        //当i<_length时循环
        while (i < _length) {
            //判断索引是否为原数组的索引
            if (i in this) {
                // 执行callback,this指向thisArg,参数有三个.分别是this[i]:值,i:索引,this:原数组.
                _arr.push(cb.call(thisArg, this[i], i, this));
            }
            //i+1
            i++;
        }
        //返回出新的数组
        return _arr;
    },
    /**
    * 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。 
    *
    * @param  {function} 用来测试数组的每个元素的函数。返回true表示保留该元素(通过测试),false则不保留。
    * @param  {Array} 可选。执行 callback 时的用于 this 的值。
    * @returns {Array}   一个新的通过测试的元素的集合的数组
    */
    filter: Array.prototype.filter || function (cb, thisArg) {
        /*var t = Object(this);
        var len = t.length;
        var res = [];
        for (var i = 0; i < len; i++) {
        if (i in t) {
        var val = t[i];
        if (cb.call(thisArg, val, i, t))
        //判断是否符合回调函数中的条件,如果符合则添加到新数组中
        res.push(val);
        }
        }
        return res;*/

        //定义自增量
        var i = 0;
        //定义数组长度
        var _length = this.length;
        //定义新的数组
        var _arr = [];

        //判断传入的cb必须是个'function',若不是返回类型错误提示
        if (typeof cb != "function")
            throw new TypeError();

        while (i < _length) {
            //如果i是原数组的索引,执行call.参数有三个.分别是this[i]:值,i:索引,this:原数组.
            if (i in this && cb.call(thisArg, this[i], i, this))
                _arr.push(this[i]);
            i++;
        }
        return _arr;
    },
    /* mdn中没有的Array方法
    reject: function (cb, UTI) { //过滤真元素
    return this.forEach(cb, UTI, "reject");
    },
    */
    /**
    * 返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
    *
    * @param  {function} 针对数组中的每个元素, 都会执行该回调函数, 执行时会自动传入下面三个参数:
    element  当前元素。
    index 当前元素的索引。
    array 调用findIndex的数组。
    * @param  {Array} 可选。执行 callback 时的用于 this 的值。
    * @returns {int}  用来判断是否满足测试函数中的第一个元素的值 没有返回-1
    */
    findIndex: Array.prototype.findIndex || function (predicate) {
        /*var o = Object(this);
        var len = o.length;
        var thisArg = arguments[1];
        var k = 0;
        while (k < len) {
        var kValue = o[k];
        if (predicate.call(thisArg, kValue, k, o)) {
        //如果找到这个元素的话则返回k
        return k;
        }
        k++;
        }
        //没有找到该元素则返回-1
        return -1;*/

        //定义自增量
        var i = 0;
        //定义数组长度
        var _length = this.length;

        //判断传入的cb必须是个'function',若不是返回类型错误提示
        if (typeof predicate != "function")
            throw new TypeError();

        while (i < _length) {
            //参数有三个.分别是this[i]:值,i:索引,this:原数组.
            if (predicate(this[i], i, this))
            //如果找到这个元素的话则返回i
                return i;
            i++;
        }
        return -1;
    },
    /**
    * 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。
    *
    * @param  {element} 被查找的元素。
    * @param  {int} 从此位置开始逆向查找。默认为数组的长度减 1,即整个数组都被查找。如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。
    * @returns {int}  数组中最后一个元素的索引,如未找到返回-1
    */
    lastIndexOf: Array.prototype.lastIndexOf || function (searchElement, fromIndex) {
        var n, k,
        t = Object(this),
        len = t.length;
        if (len === 0) {
            //如果数组的长度为零的话直接返回-1
            return -1;
        }
        n = len - 1;
        if (arguments.length > 1) {
            n = Number(arguments[1]);
            if (n != n) {
                n = 0;
            }
            else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        for (k = n >= 0
          ? Math.min(n, len - 1)
          : len - Math.abs(n); k >= 0; k--) {
            if (k in t && t[k] === searchElement) {
                // 如果有等于参数1 的元素,返回该元素
                return k;
            }
        }
        //如果上述查找没有符合条件的元素,返回-1
        return -1;

        //定义结束位置
        /* var endLength = !isNaN(parseFloat(UTI)) && isFinite(UTI) ? UTI : 0;
        //定义自减量
        var i = this.length - 1;

        
        while (i >= endLength) {
        if (USE == this[i])//如果等于就返回i索引
        return i;
        i--;
        }
        //没符合条件,返回-1
        return -1;*/
    },

    /*  mdn Array方法中无此方法   */
    /*
    sample: function (UIE, UDE) { //获取一组随机数
    UDE = UDE || this; var _USE = [], _UL = UDE.length; UIE = UIE || 1;
    for (i = 0; (i < _UL && i < UDE.length); i++) { _USE.push(UDE[U.UF.Math.getRandom(_UL)]); }
    },*/

    /**
    * 用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。
    *
    * @param  {int} 用来填充数组元素的值。
    * @param  {int} 起始索引,默认值为0。
    * @param  {int} 终止索引,默认值为 this.length。
    * @returns {Array}  修改后的数组。
    */
    fill: Array.prototype.fill || function (value) {
        var O = Object(this);
        //转换成无符号的整数
        var _len = O.length;
        var _start = arguments[1];
        var _relativeStart = _start;
        //判断start是否小于零,并将相应的值赋予变量
        var k = _relativeStart < 0 ?
            Math.max(_len + _relativeStart, 0) :
            Math.min(_relativeStart, _len);
        var _end = arguments[2];
        var _relativeEnd = _end === undefined ?
            _len : _end;
        //判断end是否小于零,并将相应的值赋予变量
        var _final = _relativeEnd < 0 ?
            Math.max(_len + _relativeEnd, 0) :
            Math.min(_relativeEnd, _len);
        //对数组进行填充
        while (k < _final) {
            O[k] = value;
            k++;
        }
        return O;
    },
    /**
    * 浅复制数组的一部分到同一数组中的另一个位置,并返回它,而不修改其大小。
    *
    * @param  {int} 0 为基底的索引,复制序列到该位置。如果是负数,target 将从末尾开始计算。
    * @param  {int} 0 为基底的索引,开始复制元素的起始位置。如果是负数,start 将从末尾开始计算。
    * @param  {int}0 为基底的索引,开始复制元素的结束位置。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。如果是负数, end 将从末尾开始计算。
    * @returns {Array}  改变了的数组。
    */
    copyWithin: Array.prototype.copyWithin || function (target, start, end) { //拷贝对象
        var O = Object(this);
        var _len = O.length;
        //转换成无符号整数
        var _relativeTarget = target;
        //判断target是否小于0,并将判断之后的值赋予变量
        var _to = _relativeTarget < 0 ?
          Math.max(_len + _relativeTarget, 0) :
          Math.min(_relativeTarget, _len);
        //start转换成无符号整数
        var _relativeStart = start;
        //判断start是否小于0,并将判断之后的值赋予变量
        var _from = _relativeStart < 0 ?
          Math.max(_len + _relativeStart, 0) :
          Math.min(_relativeStart, _len);
        var end = arguments[2];
        var _relativeEnd = end === undefined ? _len : end >> 0;
        //判断end是否小于0,并将判断之后的值赋予变量
        var _final = _relativeEnd < 0 ?
          Math.max(_len + _relativeEnd, 0) :
          Math.min(_relativeEnd, _len);
        var _count = Math.min(_final - _from, _len - _to);
        var _direction = 1;
        if (_from < _to && _to < (_from + _count)) {
            _direction = -1;
            _from += _count - 1;
            _to += _count - 1;
        }
        //循环进行数组操作
        while (_count > 0) {
            if (_from in O) {
                O[_to] = O[_from];
            } else {
                delete O[_to];
            }
            _from += _direction;
            _to += _direction;
            _count--;
        }
        //返回复制过后的数组
        return O;
    },
    /*该特性是非标准的,请尽量不要在生产环境中使用它!*/
    //toSource: function () { return JSON.stringify(this); },

    /*  mdn Array方法中无此方法   */
    //ArrayToString: function () { return JSON.stringify(this); }, //数组转换为字符串,在写api时获取后台返回的值时经常用到。

    /* IE无法兼容此方法 */
    /*keys: Array.prototype.keys || function () {
    var _UME = function (UDE) { this.i = 0; this.e = UDE; }
    _UME.prototype = {
    next: function () { //迭代
    return { value: this.i++, done: this.i >= this.e.length }
    }
    }
    return new _UME(this);
    },*/

    /**
    * 返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
    *
    * @returns {object}  一个新的 Array 迭代器对象。
    */
    /* IE无法兼容此方法 */
    //entries: Array.prototype.entries || function () { }

    //一维数组深拷贝是用concat()函数。

    //多维数组深度拷贝函数
    //重玩本关是一个难点,难度在于三维数组的拷贝,只复制地址,不复制值,这意味着通关后的数组再也回不到初始化时的数组,也就实现不了重玩本关的功能。
    //javascrit数组数据类型提供了slice(0)和concat()函数实现数组的深拷贝,但只局限于一维数组,在二维,三维,四维中不起作用。
    //为了解决此问题,特提供深度拷贝函数解决此问题。

    //递归的适合于二维数组以上的所有维度的深拷贝。
    deepCopy: function () {
        var i,
            _newarr = [];
        for (i = 0; i < this.length; i++) {
            if (Array.isArray(this[i])) {
                //深拷贝
                _newarr[i] = this[i].deepCopy(this[i]);
            }
            else {
                _newarr[i] = this[i];
            }
        }
        return _newarr;
    }
};

//ArrayBuffer兼容处理,只有在h5文件上传用到
U.UF.S.ArrayBuffer = function () {
    /**
    * ArrayBuffer slice polyfill.
    *
    * @see https://github.com/ttaubert/node-arraybuffer-slice
    */
    if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
        (function () {

            function clamp(val, length) {
                val = (val | 0) || 0;

                if (val < 0) {
                    return Math.max(val + length, 0);
                }

                return Math.min(val, length);
            }
            ArrayBuffer.prototype.slice = function (from, to) {
                var length = this.byteLength,
                    begin = clamp(from, length),
                    end = length,
                    num,
                    target,
                    targetArray,
                    sourceArray;

                if (to !== undefined) {
                    end = clamp(to, length);
                }

                if (begin > end) {
                    return new ArrayBuffer(0);
                }

                num = end - begin;
                target = new ArrayBuffer(num);
                targetArray = new Uint8Array(target);

                sourceArray = new Uint8Array(this, begin, num);
                targetArray.set(sourceArray);

                return target;
            };
        })();
    }
}

//#endregion

//#region Guid

/**
* 自定义Guid 类型
默认情况下我们给guid返回 空Guid
*/

window.Guid = U.UF.C.Guid = {
    //生成Guid
    newGuid: function () {
        var _num, i, _guid = "";
        for (i = 0; i < 32; i++) {
            _guid += Math.floor(Math.random() * 16).toString(16); //随机0  - 16 的数字 转变为16进制的字符串
            _num = Math.floor((i - 7) / 4);                        //计算 (i-7)除4
            if (_num > -1 && _num < 4 && (i == (7 + 4 * _num))) {    //会使guid中间加 "-"   形式为xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                _guid += "-";
            }
        }
        return _guid;
    },
    //空Guid
    emptyGuid: US.EMPTYGUID,
    // 返回一串无 "-" 的Guid  Dash翻译为破折号
    guidNoDash: function () {
        return Guid.newGuid().replace(/-/g, "");
    },
    //测试是不是正确的Guid  返回结果为 true  或  false
    IsGuid: function (guid) {
        return U.UF.S.Guid.test(guid);
    }
}

//#endregion
;
///<jscompress sourcefile="UPload.js" />
/*
上传下载处理类
*/
Namespace.register("U.UF.UP");

//上传总函数
/*
* @param  {array} 所有需要上传的input
* @param  {function} 上传成功回调函数
* @param  {array} 回调参数
* @param  {string} 上传后响应的处理文件地址 http://disk.1473.cn/upload.ashx
* 上下文(上一个函数与下一个函数的联系):    
r.context 回调函数的参数。上下文之间的传参,同第四个参数。
返回值说明:
由开发者定义:例如:可以定义为数组,格式如下:
array [文件在服务器的路径, 缩略图的路径, 文件id, 文件大小, 文件对应群, 文件目录id]
*/
U.UF.UP.upload = function (inputarr, url, cb, params) {
    //如果是html5,走html5
    //如果有flash,则走flash。此处难做,暂时不做。
    //如果html,走html..不能断点续传,不能解析md5.
}

//#region input上传

/**
* html input上传
*
* @param  {array} 所有需要上传的input
* @param  {string} 上传后响应的处理文件地址 http://disk.1473.cn/upload.ashx
* @param  {function} 上传成功回调函数
* @param  {array} 回调参数
*/
U.UF.UP.inputUpload = function (inputarr, url, cb, params) { //生成传输的iframe
    U.UF.UP.uploading(inputarr, cb, params, url);
}

/**
* html input上传
*
* @param  {array} 所有需要上传的input
* @param  {function} 上传成功回调函数
* @param  {array} 回调参数
* @param  {string} 上传后响应的处理文件地址 http://disk.1473.cn/upload.ashx
*/
U.UF.UP.uploading = function (inputarr, cb, params, url) { //生成传输的iframe
    var _iframe, //iframe变量
        _body = document.body, //body
        _name = Guid.guidNoDash() //用于刷新的iframe的id
    ;
    //创建一个接收上传回值的iframe,创建这个iframe主要的作用是做无刷上传,让上传的input不在页面上刷新而是在iframe里面刷新(为什么要创建iframe,因为form上传页面是会刷的,需要通过)
    _iframe = $$("iframe", { "id": _name, "name": _name, "width": 0, "height": 0, "style": { "display": "none" }, "frameBorder": 0 }, _body);
    //创建一个iframe用于做无刷上传 因为form上传的时候会刷新页面但是如果form的action属性指向的是一个iframe就不会刷新页面,这里为什么要创建跨域的iframe的因为我们项目通常不是一个域名是多个域名,等input上传结束后需要通过iframe去取值,那么下面的创建就显得非常重要
    U.UF.C.iframeSameDomain(_iframe, "", function () {
        //提交input上传
        U.UF.UP.inputUpload.submit(_iframe, inputarr, cb, params, url, _name);
    });
}

/**
* html input上传提交区域
*
* @param  {element} 用于刷新页面的iframe数组
* @param  {array} 所有需要上传的input
* @param  {function} 上传成功回调函数
* @param  {array} 回调参数
* @param  {string} 回调调用地址 允许带参数 
* @param  {string} 刷新iframe的name
*/
U.UF.UP.inputUpload.submit = function (iframe, inputarr, cb, params, url, name) {
    //input上传处理,首先创建一个form表单,然后把需要上传的input循环的放入form中,上传到服务器中
    var i, _form, _cloneinput, _changefun, _isfile;
    //跨域页面必须设置name,由于在ie8-的系列在创建元素的过程中无法设置name会出现问题,所以在这里加成成功后才能设置
    iframe.contentWindow.name = name;
    //创建一个form表单进行上传
    _form = $$("form", { "action": url, "target": name, "encoding": "multipart/form-data", "enctype": "multipart/form-data", "method": "post", "name": "loading", "style": { "display": "none"} }, document.body);
    //循环把input放在form表单里面
    for (i = 0; i < inputarr.length; i++) {
        //给上传的input设置id,如果不设置的话后台就无法获取上传的文件
        inputarr[i].name = inputarr[i].name || inputarr[i].id || Guid.newGuid();
        //由于要把input追加到上面创建的form表单里面,所以要克隆一个input
        _cloneinput = inputarr[i].cloneNode();
        //由于克隆的元素的value值还存在 也说明文件还存在,那么会导致上传同一个文件onchange事件无法触发,下面就是清理value值的兼容
        //清空input内容处理,在之前测试是用无数次的情况下会出现异常错误,所以加了try catch
        try {
            //ie清理value值的方法,比较麻烦,ie input file设置value = ""无效 所以没办法
            if (document.selection) {
                _cloneinput.select();
                document.selection.clear();
            }
            else {
                _cloneinput.value = "";
            }
        }
        catch (e) { }
        //把创建好的input代替现在要上传的input
        if (inputarr[i].parentNode) {
            inputarr[i].parentNode.replaceChild(_cloneinput, inputarr[i]); //由于要把上传的元素放在form里面进行上传处理,所以这里要克隆一个元素,否则元素就会丢失。
        }
        //form表单里面添加
        _form.appendChild(inputarr[i]); //把input添加到form表单里
        //判断上传的文件是否是file,如果不是file那么就不用multipart/form-data这种格式提交,因为只是正常的上传input里面只有文字的会产生乱码,这种乱码在java下是没有办法看的
        if (inputarr[i].type == "file") {
            _isfile = true;
        }
    }
    //如果不是文件上传 只是传输input,那么改成文本上传
    if (_isfile !== true) {
        _form.encoding = _form.enctype = "application/x-www-form-urlencoded";
    }
    //上传异步处理
    U.UF.DL.iframeLoad(iframe, function () {
        U.selectEl(_form).remove(); //元素移除
        U.UF.UP.inputUpload.asyn(iframe, inputarr, cb, params); //上传结束异步
    });
    //开始上传处理
    _form.submit();
    //拼接传参的链接,在上传的过程中添加上传用户的id,此处需要删除.因为disk.1473.cn的上传是需要做用户识别的,所以这里设置了用户id,但是这种方式是错误的,应该直接去后台获取用户id
    //    if (US && US.userInfo && US.userInfo.UserId) {
    //        url = url + (url.indexOf("?") > -1 ? "&" : "?") + "UserId=" + (US.userInfo.UserId || US.userInfo.UserId);
    //    }
}

/**
* 上传结束异步
*
* @param  {element} 用于刷新页面的iframe
* @param  {array} 所有需要上传的input
* @param  {function} 上传成功回调函数
* @param  {object} 回调参数
*/
U.UF.UP.inputUpload.asyn = function (iframe, inputarr, cb, params) {
    //跨域上传的时候,服务器返回值,在ie下已经可以直接获取到值,其他浏览器不行,这里给iframe修改src让src指向"about:blank"
    if (!(U.UF.CI.getBrowser().browser == "msie")) {
        iframe.src = "about:blank";
        //由于src重新赋值
        setTimeout(function () {
            U.UF.UP.inputUpload.callback(iframe, inputarr, cb, params); //执行回调处理
        }, 0);
    }
    //如果是ie浏览器的情况,那么直接回调,已经经过测试
    else {
        U.UF.UP.inputUpload.callback(iframe, inputarr, cb, params);  //执行回调处理
    }
}

/**
* 上传回调处理
*
* @param  {element} 用于刷新页面的iframe
* @param  {array} 所有需要上传的input
* @param  {function} 上传成功回调函数
* @param  {object} 回调参数
*/
U.UF.UP.inputUpload.callback = function (iframe, inputarr, cb, params) {
    var _value = U.UF.UP.inputUpload.getData(iframe); //获取服务器返回的值
    //上传成功后删除iframe
    U.selectEl(iframe).remove();
    //回调处理
    if (U.UF.C.isFunction(cb)) { //判断是否为函数的处理
        //调用回调的处理
        cb({
            "value": _value,  //服务器返回的数组,类似[文件在服务器的路径, 缩略图的路径, 文件id, 文件大小, 文件对应群, 文件目录id]
            "context": params, //
            "inputs": inputarr
        });
    }
}

/**
* 获取上传成功后后台返回的值
* @param  {element} 用于刷新页面的iframe
*
*/
U.UF.UP.inputUpload.getData = function (iframe) {
    var _value = null; //获取返回值的变量
    //通过iframe.contentWindow找到执行域到执行域里面获取innerHTML的方式获取值
    try {
        _value = iframe.contentWindow.document.body.innerHTML;
    }
    catch (e) { }
    //如果上面获取值的方式没有成功,就使用下面的方法获取
    if (!_value) {
        try {
            _value = iframe.contentWindow.name != iframe.id ? iframe.contentWindow.name : "";  //因为跨域上传后iframe的src的地址已经是跨域的地址,这个时候要通过Window.name方式获取跨域的值
        }
        catch (e) {

        }
    }
    //上传失败
    if (_value == null) {
        U.alert("服务器处理繁忙,上传失败");
    }
    else {
        //获取值转化成json对象
        _value = U.UF.C.toJson(_value);
    }
    return _value;
}

//#endregion

//#region html5上传

/*
* @param  {element} 所有需要上传的input
* @param  {function} 上传成功回调函数
* @param  {object} 失败的回调
{
*       "error": "U.UF.UP.error", //错误处理
*		"select": "U.UF.UP.select",  //选择文件处理
*		"getHashCallBack": "U.UF.UP.getHashCallBack", //上传解析文件的处理
*		"progress": "U.UF.UP.progress",  //解析文件md5值,和上传文件的时候的进度条处理
*		"uploadComplete": "U.UF.UP.uploadComplete",  //上传结束的处理,这个时候还没有返回值
*		"getData": "U.UF.UP.getData",  //上传结束后服务器返回的值
*		"endUpload": "U.UF.UP.endUpload", //上传结束处理
}
*/
U.UF.UP.html5Upload = function (fileinfo, succallback, callback) { //生成传输的iframe
    //进行文件加密 回调参数(进度,完成,文件hash)
    U.UF.UP.html5Upload.fileMd5(fileinfo, function (progress, finish, filehash) {
        if (finish) {//判断是否解析完成
            //获取hash后的回调处理
            if (U.UF.C.isFunction(callback.getHashCallBack)) {
                callback.getHashCallBack(filehash, fileinfo, succallback, callback.error);
            }
        }
    });
}

/*
* @param  {element} 所有需要上传的input
* @param  {function} 解析回调函数
*/
U.UF.UP.html5Upload.fileMd5 = function (file, callback) {//生成文件hash
    var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice, //分割文件的方法
        chunkSize = 2097152, // Read in chunks of 2MB
        chunks = Math.ceil(file.size / chunkSize), //分割的次数
        currentChunk = 0,
        spark = new U.UF.EC.SparkMD5.ArrayBuffer(),
        fileReader = new FileReader()
    ;
    file.fileReader = fileReader;
    //解析监听
    fileReader.onload = function (e) {
        spark.append(e.target.result);
        currentChunk++;
        //判断是否解析成功
        if (currentChunk < chunks) {
            loadNext();
            callback({ 'Loaded': currentChunk, 'Total': chunks }) // 参数:进度
        }
        else {
            callback({ 'Loaded': 100, 'Total': 100 }, true, spark.end()) // 参数:进度、 是否完成、 文件hash
        }
    };

    //解析失败监听
    fileReader.onerror = function () {
        callback(null, 'oops, something went wrong.') // 参数:进度
    };

    //解析下一步处理
    var loadNext = function () {
        var start = currentChunk * chunkSize,
            end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
        fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    }

    loadNext();
}

/*
* 判断上传的文件是否在服务器中
* @param  {file} 所有需要上传的input
* @param  {string} 上传文件的hash值
* @param  {function} 解析回调函数
*/
U.UF.UP.html5Upload.select = function (file, filehash, callback) {
    U.A.Request("http://upload.1473.cn/select", [file.name, filehash, file.size], function (r) {
        callback(r.value.fileServerName, r.value.filesize);
    });
}


/*
* 断点续传函数
* @param  {file} 文件
* @param  {int} 文件总大小
* @param  {int} 文件每次上传
* @param  {string} 文件服务器名
* @param  {int} 服务器文件大小
* @param  {fun} 成功回调函数
* @param  {fun} 失败回调函数
* @param  {int} 第几次上传次数
* @param  {int} 总上传次顺
* @param  {string} 文件hash
*/
U.UF.UP.html5Upload.loop = function (file, filehash, fileservername, filesize, callback) {
    var _xhr, _fd, _thunkto, _islast, // 切割末端
        _totalsize = file.size, // 总大小
        _eachsize = 1024 * 500, // 每次上传大小  这里是500kb
        _thunkfrom = filesize // 切割起始端
    ;
    //判断是否是最后一次上传
    if (_eachsize + filesize >= _totalsize) {
        _thunkto = _totalsize; //设置上传结束为止的大小
        _islast = true; //设置本次上传为最后一次上传
    }
    //非最后一次上传,这是每次上传为500kb
    else {
        _thunkto = _eachsize + filesize;
    }
    //创建form表单发送数据
    _fd = new FormData();
    _fd.append('theFile', file.slice(_thunkfrom, _thunkto)); // 分好段的文件
    _fd.append('filehash', filehash);
    _fd.append('fileChunk', 0); // 大小
    _fd.append('isLastChunk', _islast); // 是否最后一次上传  count === counts - 1
    _fd.append('fileServerName', fileservername); //文件名

    //调用ajax请求发送form数据
    _xhr = new XMLHttpRequest();
    file.xhr = _xhr;
    _xhr.open("post", "http://upload.1473.cn/upload", true);
    _xhr.onreadystatechange = function () {
        if (_xhr.readyState == 4 && _xhr.status == 200) {
            var _rs = JSON.parse(_xhr.responseText); //获取后台返回的值
            if (_rs.status == 200) {
                callback({ 'Loaded': _thunkto, 'Total': _totalsize }); //进度条处理
                //判断是否继续上传
                if (!_rs.isLastChunk) {
                    //继续上传
                    U.UF.UP.html5Upload.loop(file, filehash, fileservername, _thunkto, callback)

                }
                else {
                    callback(true);
                }
            }
        }
    };
    _xhr.send(_fd);
}


/**
* 删除指定上传文件
*
*/
U.UF.UP.html5Upload.deleteUploadFile = function (file) {
    if (file.fileReader) {
        file.fileReader.abort(); //停止解析
    }
    if (file.xhr) {
        file.xhr.abort(); //停止上传
    }
}

/**
* 删除所有的文件
*
*/
U.UF.UP.html5Upload.deleteUploadAllFile = function () {

}

//#endregion

//#region flash上传处理

/**
*flash上传按钮的数组,把所有加载的flash按钮放在这里,这样的话在多个地方加载flash按钮就可以在加载成功后触发事件后统一设置flash上传按钮的样式和回调事件
*{ flashbottom:flashobject, uploadtype:"*", style:{"width":"100", "height":"100"} callback:{
*       "error": "U.UF.UP.error", //错误处理
*		"select": "U.UF.UP.select",  //选择文件处理
*		"getHashCallBack": "U.UF.UP.getHashCallBack", //上传解析文件的处理
*		"progress": "U.UF.UP.progress",  //解析文件md5值,和上传文件的时候的进度条处理
*		"uploadComplete": "U.UF.UP.uploadComplete",  //上传结束的处理,这个时候还没有返回值
*		"getData": "U.UF.UP.getData",  //上传结束后服务器返回的值
*		"endUpload": "U.UF.UP.endUpload", //上传结束处理
*} }
*/
U.UF.UP.flashbottom = {};  //flash上传按钮的处理

/**
* flash按钮初始化得到
*
* @param  {element} flash对象要放置的地方
* @param  {string} flash对象名字
* @param  {object} flash按钮的样式 {"width":"100", "height":"100"}
* @param  {object} flash按钮上传的回调函数的处理 {
*       "error": "U.UF.UP.error", //错误处理
*		"select": "U.UF.UP.select",  //选择文件处理
*		"getHashCallBack": "U.UF.UP.getHashCallBack", //上传解析文件的处理
*		"progress": "U.UF.UP.progress",  //解析文件md5值,和上传文件的时候的进度条处理
*		"uploadComplete": "U.UF.UP.uploadComplete",  //上传结束的处理,这个时候还没有返回值
*		"getData": "U.UF.UP.getData",  //上传结束后服务器返回的值
*		"endUpload": "U.UF.UP.endUpload", //上传结束处理
*} }
*/
U.UF.UP.addFlashUploadBottom = function (el, name, style, callback, uploadtype) {
    var _divel,
        _width = style._width,
        _height = style._height,
        _uploadbootom = U.selectEl("object", el)[0]; //获取flash按钮
    _name = name || Guid.newGuid(); //随机生成的name
    //如果flash上传按钮,添加,这里做了ie低版本的兼容
    if (!_uploadbootom) {
        _divel = $$("div", {
            "innerHTML": "<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' class='U_MD_D_filePrew' _width='" + style._width + "' _height='" + style._height + "' id='" + _name + "' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0'>" +
                "<param name='movie' value='http://www.1473.cn/img/upload.swf' />" +
                "<param name='menu' value='false' />" +
                "<param name='wmode' value='Opaque' />" +
                "<param name='quality' value='high' />" +
                "<param name='bgcolor' value='ffffff' />" +
                "<param name='allowScriptAccess' value='always' />" +
                "<embed src='http://www.1473.cn/img/upload.swf' quality='high' bgcolor='ffffff' _width='" + style._width + "' _height='" + style._height + "' name='" + _name + "' align='middle' play='true' wmode='transparent' loop='false' quality='high' style='z-index: 0;' allowScriptAccess='always' type='application/x-shockwave-flash' pluginspage='http://www.adobe.com/go/getflashplayer'>" +
                "</embed>" +
                "</object>"
        });
        _uploadbootom = _divel.firstChild; //用上面的div去加载了object和embed标签后这里去获取
        el.insertBefore(_uploadbootom, el.firstChild); //insertBefore() 在指定子节点前插入
    }
    //把上传文件设置到flash集合中
    U.UF.UP.flashbottom[name] = {
        uploadtype: uploadtype || "*", //上传的格式
        flashbottom: U.selectEl("*" + name, el)[0], //flash上传按钮
        style: style || {}, //flash按钮的样式
        callback: callback || {} //flash按钮的回调函数,定义有注释
    };
    return _uploadbootom;
}

/**
* flash按钮加载成功的处理
*
*/
U.UF.UP.flashLoad = function () {
    var i,
        _obj = U.UF.UP.flashbottom;
    //循环给flash按钮设置处理
    for (i in _obj) {
        //调用设置
        if (_obj[i].flashbottom.setUploadStyle) {
            _obj[i].flashbottom.setUploadStyle(i, _obj[i].style, {}, _obj[i].uploadtype); //加载插件初始化
        }
    }
}

/**
* 错误处理
*
*/
U.UF.UP.error = function (e) {
    U.alert(e); //错误提醒
}

/**
* 选择文件处理
* @param  {string} flash按钮的唯一识别id
* @param  {array} 选择上传的文件数组
*
*/
U.UF.UP.select = function (bottomid, filesarr) {
    var _obj = U.UF.UP.flashbottom[bottomid]; //获取点击弹出选择文件上传的按钮对象
    _obj.callback.select(filesarr); //执行flash的回调
}

/**
* 选择文件处理
* @param  {element} 选择文件上传的flash按钮
* @param  {number} 获取FileReferenceList第几个需要解析的文件
* @param  {number} 在FileReferenceList数组里的第几个,默认是0,前端可以不传递,这里会出现一个这样的情况,用户点击上传框选择了文件,这个时候产生了一个FileReferenceList,在未上传完成的过程中又点击选择了文件,又产生了一个FileReferenceList,那么这里会出现多个FileReferenceList同时处理
*
*/
U.UF.UP.generateFileHash = function (flashbottom, fileid, i, j) {
    flashbottom.generateFileHash(fileid, 0, 0); //执行flash的回调
}

/**
* 上传解析文件的处理
* @param  {string} 解析的文件md5值
* @param  {string} flash上传按钮的id
*
*/
U.UF.UP.getHashCallBack = function (md5value, uploadid, fileid) {
    var _obj = U.UF.UP.flashbottom[uploadid]; //获取点击弹出选择文件上传的按钮对象
    _obj.callback.getHashCallBack(md5value, fileid); //执行flash的回调
}

/**
* 解析文件md5值,和上传文件的时候的进度条处理
* @param  {string} 解析的文件md5值
* @param  {string} flash上传按钮的id
* @param  {string} 进度的提醒,包括 解析中,上传中,成功
*
*/
U.UF.UP.progress = function (speedobj, uploadid, fileid, str) {
    var _obj = U.UF.UP.flashbottom[uploadid]; //获取点击弹出选择文件上传的按钮对象
    _obj.callback.progress(speedobj, fileid, str); //执行flash的回调
}

/**
* 解析文件md5值,和上传文件的时候的进度条处理
* @param  {element} 选择文件上传的flash按钮
* @param  {string} 上传文件到哪个链接下处理
* @param  {number} 获取FileReferenceList第几个需要解析的文件
* @param  {number} 在FileReferenceList数组里的第几个,默认是0,前端可以不传递,这里会出现一个这样的情况,用户点击上传框选择了文件,这个时候产生了一个FileReferenceList,在未上传完成的过程中又点击选择了文件,又产生了一个FileReferenceList,那么这里会出现多个FileReferenceList同时处理
*
*/
U.UF.UP.flashUpload = function (flashbottom, fileid, url, i, j) {
    flashbottom.upload(url, fileid, i, j); //flash上传调用
}

/**
* 上传结束的处理,这个时候还没有返回值
* @param  {object} 上传成功后返回的提示值
* @param  {string} flash上传按钮的id
*/
U.UF.UP.uploadComplete = function (e, uploadid, fileid) {
    var _obj = U.UF.UP.flashbottom[uploadid]; //获取点击弹出选择文件上传的按钮对象
    _obj.callback.uploadComplete(e, fileid); //执行flash的回调
}

/**
* 上传结束后服务器返回的值
* @param  {object} 服务器响应等到的request结果,request中的data是返回的值
* @param  {string} flash上传按钮的id
*/
U.UF.UP.getData = function (request, uploadid, fileid) {
    var _obj = U.UF.UP.flashbottom[uploadid]; //获取点击弹出选择文件上传的按钮对象
    _obj.callback.getData(request, fileid); //执行flash的回调
}

/**
* 上传结束处理
* @param  {string} flash上传按钮的id
*/
U.UF.UP.endUpload = function (uploadid) {
    var _obj = U.UF.UP.flashbottom[uploadid]; //获取点击弹出选择文件上传的按钮对象
    _obj.callback.endUpload(); //执行flash的回调
}

/**
* 移除正在上传的文件,当我们在上传的过程中,取消上传,或者是文件已经上传成功了的处理
* @param  {element} 选择文件上传的flash按钮
* @param  {int} 获取FileReferenceList第几个需要解析的文件
* @param  {int} 在FileReferenceList数组里的第几个,默认是0,前端可以不传递,这里会出现一个这样的情况,用户点击上传框选择了文件,这个时候产生了一个FileReferenceList,在未上传完成的过程中又点击选择了文件,又产生了一个FileReferenceList,那么这里会出现多个FileReferenceList同时处理
*
*/
U.UF.UP.deleteUploadFile = function (flashbottom, i, j) {
    flashbottom.deleteUploadFile(i, j); //flash上传调用
}

/**
* 删除单个选择文件弹框下所有的文件
* @param  {int} 在FileReferenceList数组里的第几个,默认是0,前端可以不传递,这里会出现一个这样的情况,用户点击上传框选择了文件,这个时候产生了一个FileReferenceList,在未上传完成的过程中又点击选择了文件,又产生了一个FileReferenceList,那么这里会出现多个FileReferenceList同时处理
*
*/
U.UF.UP.deleteReferenceFile = function (flashbottom, i) {
    flashbottom.deleteReferenceFile(i); //flash上传调用
}

/**
* 删除所有的文件
*
*/
U.UF.UP.deleteUploadAllFile = function (flashbottom) {
    flashbottom.deleteUploadAllFile(); //flash上传调用
}

//#endregion

//#region 下载

/**
* 文件下载区域
*
* @param  {string} 文件下载的名字 名字.jgp
* @param  {string} 下载文件的路径 fa.1473.cn/aa.jpg
* @param  {string} 下载文件的处理类的地址 http://disk.1473.cn/USUpfile.ashx typename=" + (fun || "UploadFile"
*/
U.UF.UP.download = function (filename, filepath, url) {
    var _filenameinput = $$("input", { "type": "text", "value": encodeURIComponent(filename), "name": "filename" }), //下载下来的文件名
        _filepathinput = $$("input", { "type": "text", "value": filepath, "name": "filepath" }); //下载的文件在服务器的路径
    //调用上传的接口进行下载,实际上传接口的作用是把input上传到服务器进行响应
    U.UF.UP.inputUpload([_filenameinput, _filepathinput], url);
}

//#endregion

//#region 帮助处理

/**
* 获取上传的名字和类型
*
* @param  {string} 文件名+类型
* @return {array} 
----------[0] 文件名
----------[1] 文件类型 
*/
U.UF.UP.getFileNameAndExtension = function (filename) {
    filename = filename.toLocaleLowerCase(); //把文字转成消息 如 gg.JPG 转成 gg.jpg 这样下面判断容易
    var _num = filename.lastIndexOf("."), //文件后缀.所在的位置
        _index = filename.lastIndexOf("\\"),
        _xindex = filename.lastIndexOf("/"),
        _name = filename.substr((_index > _xindex ? _index : _xindex) + 1, _num), //名字
        _extension = filename.substr(_num + 1) //后缀
        ;
    return [_name, _extension]; //文件名和后缀数组
}

/**
* 判断是否为图片类型,fun为文件名,比如"aaaa.jpg"
*
* @param  {string} 文件名
* @param  {boolean} 是否为图片
*/
U.UF.UP.isImg = function (name) {
    var _extension = U.UF.UP.getFileNameAndExtension(name.toLowerCase())[1]; //获取文件的后缀
    return ["jpg", "gif", "png", "bmp", "jpeg"].indexOf(_extension) > -1; //根据后缀判断文件是否为图片
}

/**
* 文件由小转大
*
* @param  {string} 文件
*/
U.UF.UP.minUnitToMaxUnit = function (filesize) {
    var _unitarr = ["B", "KB", "M", "G", "TB"], //指定的文件类型
        _unit = (filesize + "").replace(U.UF.S.Num, ""), //获取单位
        i = _unitarr.indexOf(_unit) < 0 ? 0 : _unitarr.indexOf(_unit); //现在单位对应下标
    filesize = parseFloat(filesize); //获取文件大小
    //判断文件大小
    while (filesize > 1024) {
        filesize /= 1024; //每次除以1024,往下一个单位去变化
        i++; //单位
    }
    return parseInt(filesize.toFixed(2)) + _unitarr[i]; //文件大小加单位
}

/**
* 获取最小单位的大小
*
* @param  {string} 文件大小 如 10000B 10240KB 等等
*/
U.UF.UP.maxUnitToByte = function (filesize) {
    var _unitarr = ["B", "KB", "M", "G", "TB"], //指定的文件类型
        _unit = (filesize + "").replace(U.UF.S.Num, ""), //获取单位
        i = _unitarr.indexOf(_unit); //看看单位对应的大小
    i = i < 0 ? 0 : i; //看看转成最小单位需要*i个1024个次方
    return parseFloat(filesize) * Math.pow(1024, i); //获取最大单位 
}

//#endregion
;
///<jscompress sourcefile="WindowFunction.js" />
Namespace.register("U.UF.F");

//#region 窗体放大缩小

//窗体的全局变量
U.UF.F.isTop = false; //置顶的全局判断
U.UF.F.hisTory = true; //判断是否保留最大化之前的窗体宽、高、top、left值

/*
*   遮罩框
*  由于在拖动拉伸等过程中可能会触发到其他iframe,这里就是全局遮罩,让拖动和拉伸的过程中,不回出发到下面的iframe
*/
U.UF.F.maskFrame = function () {
    return $$("div", { "style": { "cssText": "width:100%;height:100%;position:absolute;top:0;left:0;"} }, document.body);
}

/*
** 作用:窗体的最大化和最小化功能
** @param {element} el 整个窗体的元素
*/
U.UF.F.windowZooming = function (el) {
    var _csstext = el.initcsstext, //初始化的csstext
        _ismax = el.ismaximize; //判断窗体是否已经最大化了
    //如果最大化了,那么就把他缩小
    if (_ismax) {
        el.style.cssText = _csstext;
        el.ismaximize = false;
    }
    //最大化处理
    else {
        el.initcsstext = el.style.cssText; //获取原本的csstext值
        el.ismaximize = true;
        //设置窗体最大化
        U.selectEl(el).css({
            "width": "100%",
            "height": "100%",
            "top": "0px",
            "left": "0px"
        });
    }
    U.MD.F.W.reSize();
}

/*
** 作用:窗体的最小化功能
** @param {element} el 整个窗体的元素
*/
U.UF.F.windowMinimize = function (el) {
    //添加样式,实现动画效果,并且逐渐隐藏整个窗体
    el.style.cssText += "display:none";
    //-ms-transform:scale(0.5);-webkit-transform:translateX(100%); -o-transform:scale(0.5); transform:scale(0.5);
}

/*
** 作用:窗体的关闭功能
** @param {element} el 整个窗体的元素
** @param {string} str 操作指令
*/
U.UF.F.closeWindow = function (el, str) {
    var _el = U.selectEl(el); //获取整个窗体的元素
    //    if (_el[0].style.display != "none" && str == "remove") {//判断窗体是否被隐藏,并且操作指令为remove
    //        _el.remove(); //移除整个窗体
    //        _el = null; //移除整个窗体
    //    }
    //    else {
    _el.css("display", "none");
    //    }
}

/*
** 作用:窗体的居中功能
** @param {element} el 整个窗体的元素
*/
U.UF.F.windowTopCenter = function (el) {
    //异步弹出窗体置顶,因为在我们的窗体点击的时候回切换置顶,但在在里面点击应用的时候,会导致先置顶应用(调用了该函数).然后又制定点击对应的窗体。
    //setTimeout(function () {
    //获取实际高度或者是当前窗口对于窗口显示区左上角的Y位置或者是整个body的实际高度
    var _scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop,
    //获取整个页面的宽度
        _iwidth = document.documentElement.clientWidth,
    //获取整个浏览器的宽度
        _iheight = document.documentElement.clientHeight; //_scrollTop * 2
    el.style.display = "block"; //先显示窗体
    _zindex = (US || parent.US).ZINDEX++;
    U.selectEl(el).css({
        "zIndex": _zindex,
        //获取整个窗体的left的值为浏览器窗口文档显示区域的宽度不包括滚动条减去窗体的文档显示区域在除以2再加上实际宽度
        "left": (_iwidth - el.clientWidth) / 2 + "px",
        //获取整个窗体的left的值为浏览器窗口文档显示区域的高度不包括滚动条减去窗体的文档显示区域在除以2再加上实际高度
        "top": (_iheight - el.clientHeight) / 2 + "px"
    });
    //}, 0);
}
/*
** 作用:窗口的置顶功能
** @param {element} el 整个窗体的元素
** @param {string} str 是否为true
1、获取点击元素
2、给点击元素父级元素的z-index+1
*/
U.UF.F.topWindow = function (el) {
    var _zindex,
        _el1 = U.UF.F.getWindow(el), //通过U.UF.F.getWindow()获取需要进行置顶的窗体元素
		_el3; //获取需要置顶元素的父级元素
    if (_el1 && _el1.length || el && el.length) {//判断是否有需要置顶的窗体元素
        for (var i = 0; i < _el1.length; i++) {//循环判断有几个窗体元素
            _el3 = U.selectEl(_el1[i]).Parent();
            //判断 是否有获取需要置顶的窗体元素的父级元素 并且 需要置顶的元素是否符合document.body或者id是否符合"usestudio_server"或者id是否符合"U_MD_Home"三种中的一种,并且是否需要置顶的元素"__top__"不为false,并且操作指令为true或者返回值在字符串中首次出现的位置是否为-1
            if (_el3 && (_el3 == document.body || _el3.id == "usestudio_server" || _el3.id == "U_MD_Home") && ($(_el1[i]).attr("__top__") != "false" && _el1[i]["__top__"] != "false")) {
                _zindex = (US || parent.US).ZINDEX++;
                //如果符合全部要求,则给置顶元素添加一个style样式,z-index每一次置顶都在现有的z-index中加1,并且显示出来
                U.selectEl(_el1[i]).addAttrArray({ "style": { "cssText": _el1[i].style.cssText + ";z-index:" + _zindex + ";display:block"} });
            }
        }
    }
}

/*
** 作用:获取顶层窗体的功能
** @param {element} el 整个窗体的元素
*/
U.UF.F.getWindow = function (el) {
    var _arr = [], //先定义一个用于存储需要置顶元素的元素
		_el2 = el, //获取整个窗体的元素
		_el3 = document.body, //获取整个文档的body部分,不包括除body外的一切
		_el4 = U.selectEl("#U_MD_Home")[0] || U.selectEl("#usestudio_server")[0] || _el3; //获取满足三个条件中的一个的元素
    //判断是否有满足三个条件中的一个的元素
    if (_el4) {//如果有,则进行下面的语句
        //循环语句,整个窗体的元素为元素的offsetParent,并且.获取的窗体元素不为整个body的部分,也不是满足获取id为U_MD_Home和id为usestudio_server的元素,并且条件满足的情况下进行循环批判断,直到结果出现
        while ((_el2 = U.UF.EL.offsetParent(_el2, true)) && (_el2 && (_el2 != _el4 && _el2 != _el3))) {//因为这条语句没有循环限定次数,所以适用while循环语句
            if (_el2.style.position != "relative") {
                _arr.push(_el2); //如果条件满足,则向_arr这个存储元素的末尾添加一个窗体元素
            }
            _el2 = _el2.parentNode; //并且把窗体的父节点赋值给新的_el2元素

        }
        return _arr; //最后返回需要置顶的窗体元素的数组
    }
}

/*
**	作用:桌面窗体自动分层次处理,点击窗口自动分层,不会叠加
**	@param {callback} cb 回调函数,调用分层函数
**	@param {boolean} b 操作指令,知否为true或者false
**	@param {element} el 获取窗体元素
*/
U.UF.F.clickTopWindow = function (cb) {
    //设置点击置顶的功能
    U.selectEl(document.body).bind({
        mousedown: function () {
            //判断点击置顶有回调函数则回调
            if (U.UF.C.isFunction(cb)) {
                cb(event.srcElement, true);
            }
            //置顶窗体处理
            top.U.UF.F.topWindow(event.srcElement, true);
        }
    });
}

//#endregion

//#region 拉伸

/*
* 拉伸函数处理
*
* 1 @param obj1 = {object} 需要拉伸的窗体
* 3 @param str ={string}  判断拉伸是哪个方位
实例:U.UF.F.stretching($(".窗体")[0],拉伸类型)
拉伸类型:
bottom  * 向下
right  * 向右
top   * 向上
left  * 向左
rightBottom  * 右下
rightTop  * 右上
leftTop  * 左上
leftBottom * 左下
*/
U.UF.F.stretching = function (obj1, str) {
    var e = window.event; //获取当前鼠标点击事件
    //target 就是这个对象
    //target = e.srcElement || e.target
    //这个对象的值
    //targetValue = target.value;
    var _disX, _disY, _dragMinWidth = 70, _dragMinHeight = 70;
    //_dragMinWidth _dragMinHeight设置窗口拉伸最小宽度和高度
    // obj2.onmousedown = function (e) { //div的点击执行
    //e = e || event;  //获取当前event的信息赋予e
    e.preventDefault(); //取消event事件的默认动作
    _disX = e.clientX; //当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标 
    _disY = e.clientY; //当事件被触发时鼠标指针向对于浏览器页面(或客户区)的垂直坐标
    var _iparenttop = obj1.offsetTop; //当前窗口距离可视窗口顶部的距离
    var _iparentleft = obj1.offsetLeft; //当前窗口距离可视窗口左部的距离
    var _iparentwidth = obj1.offsetWidth; //当前窗口的宽度
    var _iparentheight = obj1.offsetHeight; //当前窗口的高度
    if (!$("#U_UF_F_drag_flag")[0]) {
        var _div = $$("div", { "style": { "cssText": "width: 100%;height: 100%;z-index: 99999;position: absolute;top:0;left:0;" }, "id": "U_UF_F_drag_flag" }, document.body);
        //    _top = U.selectEl(U.UF.UI.form.allForm[_drag.id].header).height();
        //   U.selectEl(_div)[0].style.top = _top + "px";
    }
    var _windowfun = {
        "mousemove": function (e) { //拉伸移动执行
            e = e || event; //获取在鼠标移动的时候event的信息
            var _iL = e.clientX - _disX - 3; //返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标-减去-之前窗体距离左边的距离 剩下的就是改变后的宽度
            //_iL 相当于 窗体要移动的距离
            var _iT = e.clientY - _disY; //返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的垂直坐标-减去-之前窗体距离顶部的距离 剩下的就是改变后的高度
            //_iT 相当于 窗体要移动的高度
            var _maxw = document.documentElement.clientWidth - _iparentleft - 2; //获取窗体向右扩张最大宽度(网页可视宽度减去-当前窗口距离可视窗口左部的距离)剩下最大的宽度
            var _maxh = document.documentElement.clientHeight - _iparenttop - 2; //获取窗体向下扩张最大高度 (网页可视高度减去-当前窗口距离可视窗口顶部的距离)剩下最大的高度
            if (str == "bottom") {
                var _ih = _iT + _iparentheight; //获取拉伸后窗体改变的高度
                if (_ih < _dragMinHeight) { _ih = _dragMinHeight } else if (_ih > _maxh) { _ih = _maxh; };
                //第一先判断改变后的高度有没有低于自己设置的最小高度如果小于就命改变后的高度变成最小高度
                //第二判断改变后的高度有没有大于 之前获取的最大高度  如果大于就命 改变后的高度变成最大高度
                obj1.style.height = _ih + 'px'; //执行

            }
            if (str == "right") {
                var _iw = _iL + _iparentwidth//获取拉伸后窗体改变的宽度  
                if (_iw < _dragMinWidth) {
                    _iw = _dragMinWidth
                } else if (_iw > _maxw) {
                    _iw = _maxw;
                }; //判断改变后的宽度有没有低于自己设置的最小宽度,如果有就变成最小的宽度,
                //第二判断改变后的宽度有没有大于自己设计的最大宽度如果有就命改变后的宽度变成最大的宽度
                obj1.style.width = _iw + 'px'; //执行
            }
            if (str == "top") {
                var _ih = _iparentheight - _iT  //获取拉伸后窗体改变的高度  向下拉就是窗体剩余的高度
                obj1.style.top = _iparenttop + _iT + 'px'; //执行窗体改变后距离可视窗口头部的距离
                if (obj1.style.top < '0') {
                    obj1.style.top = '0px';
                    document.onmousemove = null;
                } //判断刚刚赋予的值有没有小于0 防止窗口拉伸到外面
                if (_ih < _dragMinHeight) {//之前定义了一个属性值高度防止小于窗体高度
                    var _bh = _ih  //赋予值
                    _ih = _dragMinHeight; //赋予值
                    obj1.style.top = (_iparenttop + _iT) - (_dragMinHeight - _bh) + 'px';  //(之前距离头部的距离 + 要添加的y值) - (之前设置的最小高度值 - 获取拉伸后窗体改变的高度)
                }
                obj1.style.height = _ih - '2' + 'px'; //赋予
            }
            if (str == "left") {
                var _iw = _iparentwidth - _iL // 窗体改变前的宽度 减去 窗体拉伸的长度  
                obj1.style.left = _iparentleft + _iL + 'px'; //当前窗口距离可视窗口左部的距离 + 窗体要移动的距离 (通常为负数)
                if (_iw < _dragMinWidth) {//之前定义了一个属性值宽度防止小于窗体宽度
                    var _bl = _iw
                    _iw = _dragMinWidth
                    obj1.style.left = (_siparentleft + _iL) - (_dragMinWidth - _bl) + 'px'; //(之前距离左边的距离 + 要添加的x值) - (之前设置的最小宽度值 - 获取拉伸后窗体改变的宽度)
                }
                obj1.style.width = _iw - '2' + 'px';
            }
            if (str == "rightBottom") {
                var _iw = _iL + _iparentwidth;  //获取拉伸后窗体改变的宽度
                var _ih = _iT + _iparentheight; //获取拉伸后窗体改变的高度
                if (_iw < _dragMinWidth) {//之前定义了一个属性值宽度防止小于窗体宽度
                    _iw = _dragMinWidth  //赋予值
                } else if (_iw > _maxw) {
                    _iw = _maxw;
                }; //防止扩张的时候超出向右扩张最大范围
                obj1.style.width = _iw - '2' + 'px';  //-2 是窗体的div本身的厚度 
                if (_ih < _dragMinHeight) {//之前定义了一个属性值高度防止小于窗体高度
                    _ih = _dragMinHeight;  //赋予值
                } else if (_ih > _maxh) {
                    _ih = _maxh;
                }; //防止扩张的时候超出向下扩张最大高度
                obj1.style.height = _ih + 'px';  //赋予值

            }
            if (str == "rightTop") {
                var _iw = _iL + _iparentwidth;  //获取拉伸后窗体改变的宽度
                var _ih = _iparentheight - _iT; //获取拉伸后窗体改变的高度  
                obj1.style.top = _iparenttop + _iT + 'px';  //当前窗口距离可视窗口顶部的距离 + 改变后的距离
                if (obj1.style.top < '0') { obj1.style.top = '0px'; document.onmousemove = null; } //为了防止拉伸的时候超出边界 
                if (_iw < _dragMinWidth) {//之前定义了一个属性值宽度防止小于窗体宽度
                    _iw = _dragMinWidth  //赋予值
                } else if (_iw > _maxw) { _iw = _maxw; };  //如果改变后的宽度超出最大的宽度则。
                obj1.style.width = _iw + 'px';  //赋予值
                if (_ih < _dragMinHeight) {//之前定义了一个属性值高度防止小于窗体高度
                    var _bh = _ih   //赋予值
                    _ih = _dragMinHeight;  //赋予值
                    obj1.style.top = (_iparenttop + _iT) - (_dragMinHeight - _bh) + 'px';  //(之前距离头部的距离 + 要添加的y值) - (之前设置的最小高度值 - 获取拉伸后窗体改变的高度)
                } else if (_ih > (_iparenttop + _iparentheight)) {
                    _ih = (_iparenttop + _iparentheight)
                }; //如果扩展的高度超过了  (当前窗口距离可视窗口顶部的距离 + 当前窗口的高度)则防止扩张的时候超出范围
                obj1.style.height = _ih - '2' + 'px'; //赋予值

            }
            if (str == "leftTop") {
                var _iw = _iparentwidth - _iL   // 窗体改变前的宽度 减去 窗体拉伸的长度  
                obj1.style.left = _iparentleft + _iL + 'px'; //当前窗口距离可视窗口左部的距离 + 窗体要移动的距离 (通常为负数)
                var _ih = _iparentheight - _iT //获取拉伸后窗体改变的高度  
                obj1.style.top = _iparenttop + _iT + 'px'; //当前窗口距离可视窗口顶部的距离 + 改变后的距离
                if (obj1.style.top < '0') { obj1.style.top = '0px'; document.onmousemove = null; } //为了防止拉伸的时候超出边界 
                if (_iw < _dragMinWidth) {//之前定义了一个属性值宽度防止小于窗体宽度
                    var _bl = _iw;    //赋予值
                    _iw = _dragMinWidth; //赋予值
                    obj1.style.left = (_iparentleft + _iL) - (_dragMinWidth - _bl) + 'px'; //(之前距离左边的距离 + 要添加的x值) - (之前设置的最小宽度值 - 获取拉伸后窗体改变的宽度)
                } else if (_iw > (_iparentleft + _iparentwidth)) {
                    _iw = (_iparentleft + _iparentwidth)
                }; //如果改变后的宽度超过当前窗口距离可视窗口左部的距离 + 窗体改变前的宽度则
                obj1.style.width = _iw - '2' + 'px'; //赋予值
                if (_ih < _dragMinHeight) {//之前定义了一个属性值高度防止小于窗体高度
                    var _bh = _ih; //赋予值
                    _ih = _dragMinHeight; //赋予值
                    obj1.style.top = (_iparenttop + _iT) - (_dragMinHeight - _bh) + 'px'; //(之前距离头部的距离 + 要添加的y值) - (之前设置的最小高度值 - 获取拉伸后窗体改变的高度)
                } else if (_ih > (_iparenttop + _iparentheight)) {
                    _ih = (_iparenttop + _iparentheight)
                }; //如果扩展的高度超过了  (当前窗口距离可视窗口顶部的距离 + 当前窗口的高度)则防止扩张的时候超出范围
                obj1.style.height = _ih - '2' + 'px'; //赋予值

            }
            if (str == "leftBottom") {
                var _iw = _iparentwidth - _iL; // 窗体改变前的宽度 减去 窗体拉伸的长度  
                obj1.style.left = _iparentleft + _iL + 'px'; //当前窗口距离可视窗口左部的距离 + 窗体要移动的距离 (通常为负数)
                var _ih = _iT + _iparentheight; //获取拉伸后窗体改变的高度
                if (_iw < _dragMinWidth) {//之前定义了一个属性值宽度防止小于窗体宽度
                    var _bl = _iw; //赋予值
                    _iw = _dragMinWidth; //赋予值
                    obj1.style.left = (_iparentleft + _iL) - (_dragMinWidth - _bl) + 'px'; //(之前距离左边的距离 + 要添加的x值) - (之前设置的最小宽度值 - 获取拉伸后窗体改变的宽度)
                } else if (_iw > (_iparentleft + _iparentwidth)) {
                    _iw = (_iparentleft + _iparentwidth)
                }; //如果改变后的宽度超过当前窗口距离可视窗口左部的距离 + 窗体改变前的宽度则
                obj1.style.width = _iw - '2' + 'px';  //赋予值
                if (_ih < _dragMinHeight) {//之前定义了一个属性值高度防止小于窗体高度
                    _ih = _dragMinHeight; //赋予值
                } else if (_ih > _maxh) {
                    _ih = _maxh;
                }; //防止扩张的时候超出向下扩张最大高度
                obj1.style.height = _ih - '2' + 'px'; //赋予值

            }
            if (((str == 'left' || str == 'leftTop' || str == 'leftBottom') && _iw == _dragMinWidth) || ((str == 'top' || str == 'rightTop' || str == 'leftTop') && _ih == _dragMinHeight)) {
                document.onmousemove = null;
            }; //是为了当使用时拉伸时不会低于最小值

            return false;

        },
        "mouseup": function () {//拉伸结束
            document.onmousemove = null;
            document.onmouseup = null;
            if ($("#U_UF_F_drag_flag")[0]) {
                U.selectEl("#U_UF_F_drag_flag").remove();
            }
            U.selectEl(document.body).unbind(_windowfun);
        }
    }
    U.selectEl(document.body).bind(_windowfun);
}

//#endregion

//#region 拖动窗体

/*
* 函数功能:元素拖动函数,初始化函数
*
* @param  el1 {element} 触发拖拽的对象元素
* @param  el2 {element} 被拖拽的对象元素
* @param  cb1  {function} 每次拖动时,触发的回调函数
* @param  cb2  {function} 拖动完毕时,触发的回调函数
*/
U.UF.F.drag = function (el, cb1, cb2) {
    /*
    * _x {number} 记录元素的left值距离屏幕的差距
    * _y {number} 记录元素的top值距离屏幕的差距
    * _drag {element} 被拖拽的对象元素
    * */
    var _x, _y, _l, _t, _drag;
    var _event = event || window.event;  //var _event = event || window.event;这句话就是定义了一个变量来获取事件对象,因为不同的浏览器获取事件对象的方法有点不太一样,IE下是window.event,标准下是event,为了兼容所以写了event || window.event.
    /*
    * 说明:
    * _event {element} 事件源
    * _x {element} 记录元素的left值距离屏幕的差距
    * _y {element} 记录元素的top值距离屏幕的差距
    * */
    _drag = el; //赋值被拖拽的对象元素

    _x = _event.clientX; //记录元素的left值距离屏幕的差距
    _y = _event.clientY; //记录元素的top值距离屏幕的差距
    _l = _drag.offsetLeft; //元素的左偏移
    _t = _drag.offsetTop; //元素的右偏移

    /*
    * 说明:对document树,进行事件的绑定。
    * */
    var _windowfun = {
        /*
        * 说明:绑定鼠标移动事件
        * _event {element} 事件源
        * */
        "mousemove": function (event) {
            //如果被拖拽的对象存在,执行以下代码
            if (_drag) {
                /*
                * 说明:变量说明
                * _event {element} 事件源
                * _left  {number} 元素水平移动的距离
                * _top   {number} 元素垂直移动的距离
                * body   {element} 页面body对象
                * */
                var _event = event || window.event, //var _event = event || window.event;这句话就是定义了一个变量来获取事件对象,因为不同的浏览器获取事件对象的方法有点不太一样,IE下是window.event,标准下是event,为了兼容所以写了event || window.event.
                    _newx = _event.clientX - _x,
                    _newy = _event.clientY - _y,
                    _left = _newx + _l, // 移动后鼠标的水平距离减去元素未移动时的水平距离,等到元素水平移动的距离。
                    _top = _newy + _t, // 移动后鼠标的垂直距离减去元素未移动时的垂直距离,等到元素垂直移动的距离。 
                    _body = U.selectEl(document.body)[0]; //页面body对象,用于判断是否超出屏幕可视区域
                //                if (_left < 0) _left = 0; //如果元素水平移动超出屏幕最左侧,则使元素水平距离在屏幕的最左侧
                //                if (_left > _body.offsetWidth - _drag.offsetWidth) _left = _body.offsetWidth - _drag.offsetWidth; //如果元素水平移动超出屏幕最右侧,则使元素水平距离在屏幕的最右侧
                //                if (_top < 0) _top = 0; //如果元素垂直移动超出屏幕最上侧,则使元素垂直距离在屏幕的最上侧
                //                if (_top > (_body.offsetHeight - _drag.offsetHeight)) _top = (_body.offsetHeight - _drag.offsetHeight); //如果元素垂直移动超出屏幕最下侧,则使元素垂直距离在屏幕的最下侧
                //                _drag.style.cursor = 'move'; //改变被拖拽的对象元素的鼠标形状
                _drag.style.left = _left + 'px'; //改变被拖拽的对象元素的水平位置
                _drag.style.top = _top + 'px'; //变被拖拽的对象元素的垂直位置
                if (!$("#U_UF_F_drag_flag")[0] && (_newx != 0 || _newy != 0)) {
                    var _div = $$("div", { "style": { "cssText": "width: 100%;height: 100%;z-index: 99999;position: absolute;top:0;left:0;" }, "id": "U_UF_F_drag_flag" }, document.body);
                }
                if (cb1 && typeof cb1 == "function" && _newx != 0 && _newy != 0) { cb1(); } //如果有拖动时的回调函数,则执行回调函数。
            }
        },
        /*
        * 说明:绑定松开鼠标事件
        * event {element} 事件源
        * */
        "mouseup": function (event) {
            //如果有拖动完成的回调函数,则执行回调函数。
            if (_drag && cb2 && typeof cb2 == "function") { cb2(el) };
            if ($("#U_UF_F_drag_flag")[0]) {
                U.selectEl("#U_UF_F_drag_flag").remove();
            }
            //清空被拖拽的对象元素
            _drag = null;
            U.selectEl(document.body).unbind(_windowfun);
        }
    }
    U.selectEl(document.body).bind(_windowfun);
}

//#endregion

//#region 拖动选择元素 暂未修改

/*
* 直接拖动元素不带虚拟框 一般常用于图标移动
*
* @param  {element} 拖动元素
*/
U.UF.F.dragSelect = function (el, fun) {
    //右键处理
    if (event.button != 2) {
        var _x,
            _y,
            _dragel,
            _mousep = U.UF.EL.getMousePosition(el), //鼠标位置
            _record = { x: _mousep.x, y: _mousep.y },
        //拖动函数的处理
            _mousemove = function () {
                //拖动的处理
                U.UF.F.dragSelect.drag(el, _mousep, _dragel, fun, _record);
            },
        //拖动释放的处理
            _mouseup = function () {
                U.selectEl(_dragel).remove();
                //释放取消绑定的处理
                U.selectEl(document).unbind({
                    "mousemove": _mousemove,
                    "mouseup": _mouseup

                });
                U.selectEl(el).unbind({
                    "scroll": _mousemove
                });
            };
        //记录滚动条位置
        _mousep.left = el.scrollLeft;
        _mousep.top = el.scrollTop;
        _x = _mousep.x; //鼠标的x轴坐标
        _y = _mousep.y; //鼠标的y轴坐标
        //创建选择元素
        _dragel = $$("div", { "style": { "cssText": "position:absolute;width:0;height:0;font-size:0;margin:0;padding:0;border:1px solid #89b1e6;background-color:#c3d5ed;z-index:1000;filter:alpha(opacity:60);opacity:.6;background-image: url(http://www.1473.cn/img/UXZT.png); display: inline-block; z-index: 1000; zoom: 1;" + "top:" + _y + "px;left:" + _x + "px;zIndex:" + US.ZINDEX + 1} }, el);
        //绑定元素的处理
        U.selectEl(document).bind({
            "mousemove": _mousemove,
            "mouseup": _mouseup
        });
        U.selectEl(el).bind({
            "scroll": _mousemove
        });
    }
    else {
        if (el.dragel) {
            el.dragel = null;
        }
    }
}

/*
* 直接拖动元素不带虚拟框 一般常用于图标移动
*
* @param  {element} 拖动元素
*/
U.UF.F.dragSelect.drag = function (el, mouseup, dragel, fun, record) {
    var _m = event.type == "scroll" ? record : U.UF.EL.getMousePosition(el), //当前鼠标的位置 
        _left = mouseup.x + mouseup.left, //滚动条left
        _top = mouseup.y + mouseup.top, //滚动条top
        _ctop = _m.y + el.scrollTop,
        _cleft = _m.x + el.scrollLeft,
        _w = Math.abs(_cleft - _left), //拖动后的长
        _h = Math.abs(_ctop - _top), //拖动后的宽
        _l = Math.min(_cleft, _left), //拖动后的left
        _t = Math.min(_ctop, _top)    //拖动后的top
    ;
    //如果是滚动出发的则找不到鼠标的位置 所以需要通过记录去找
    record.x = _m.x;
    record.y = _m.y;
    //拉动大小变化 
    U.selectEl(dragel).addAttrArray({ "style": { "cssText": "width:" + _w + "px;height:" + _h + "px;top:" + _t + "px;left:" + _l + "px;"} });
    //设置拉伸选取的处理
    U.UF.F.dragSelect.isLocation(dragel, el, { "width": _w, "height": _h, "left": _l, "top": _t }, fun);
}

/*
* 选择元素逻辑范围逻辑
*
* @param  {object} 选择的范围
*/
U.UF.F.dragSelect.isLocation = function (dragel, el, obj, fun) {
    var i,
        _left,
        _top,
        _width,
        _height,
        _arr = [],
        _child = U.selectEl(el).Child() //所有的拖选取的元素
    ;
    //循环子元素的处理
    for (i = 0; i < _child.length; i++) {
        //处理的元素不是拖选元素
        if (_child[i] != dragel) {
            _left = _child[i].offsetLeft;
            _top = _child[i].offsetTop;
            _width = _child[i].offsetWidth;
            _height = _child[i].offsetHeight;
            //范围判断
            if ((obj.left < _left + _width && obj.left + obj.width > _left) && (obj.top < _top + _height && obj.top + obj.height > _top)) {
                _arr.push(_child[i]);
            }
        }
    }
    //回调处理
    if (fun) {
        fun(_arr);
    }
}


///*
//* 获取元素选择范围
//*
//* @param  {object} 选择的范围
//*/
//U.UF.F.dragSelect.getElementRange = function (el, obj) {//
//    //    var _UL, _UDE = [0, 0];
//    //    _UDE[4] = _UL = Math.floor(this.ElO["SW"] / this.W); //每行占位的个数
//    //    _UDE[0] = ((Math.floor(ULE["Y"] / this.H) - 1) * _UL); //开始的位置
//    //    _UDE[1] = _UDE[0] + ((Math.ceil((ULE["BY"]) / this.H) - Math.floor(_UDE[0] / _UL)) * _UL); //结束的位置
//    //    _UDE[2] = Math.min(Math.ceil(ULE["X"] / this.W), _UL) - 1; _UDE[3] = Math.min(Math.ceil(ULE["BX"] / this.W), _UL) - 1; return _UDE;
//}


//#endregion

//#region 拖拉变化

///*
//* 获取元素选择范围
//*
//* @param  {object} 拖选的元素
//* @param  {object} 拖选的传参
//*/
//U.UF.F.dragTable = function (el, obj) {
//    if (el) {
//        obj = obj || {};
//        new U.UF.F.dragTable.init(el, obj); //初始化拖选
//    }
//}

///*
//* 拖动初始化
//*
//* @param  {object} 拖选的元素
//* @param  {object} 拖选的传参
//*/
//U.UF.F.dragTable.init = function (el, obj) {
//    var _UDTD = U.selectEl(el),
//    _UDSD = _UDTD.parentElement(), //上级元素
//    _UDPD = _UDTD.prev(), //上面的兄弟节点
//    _UDND = _UDTD.next(); //下面的兄弟节点
//    //添加初始化值
//    this.UDPD = _UDSD; //上级元素
//    this.w = _UDSD.width(); //当前长度
//    this.pw = _UDSD.parentElement().width(); //总长度
//    this.el = el; //拖动的元素
//    this.UE = U.UF.EL.getMousePosition(); //鼠标的位置
//    this.prev = _UDPD; //上面的兄弟节点
//    this.next = _UDND; //下面的兄弟节点
//    this.uw = [_UDPD.width(), _UDND.width()]; //兄弟节点长度

//    //拖动参数设置
//    U.UF.C.AddObj(this, obj);
//    //聚焦
//    el.setCapture();
//    //拖动元素
//    U.selectEl(document.body).bind({
//        "mousemove": (this.move = U.UF.C.apply(this, obj.tf ? this.dragB : this.drag)),
//        "mouseup": (this.mup = function () { this.up(); })
//    });
//}

//U.UF.F.dragTable.init.prototype = {
//    //拖动左右使用
//    drag: function () {
//        var _UDVD = this.prev, //上级元素
//        _UDND = this.next, //下面的兄弟节点
//        _UW = this.uw, //不变的大小
//        _UE = this.UE, //鼠标的位置
//        _UME = U.UF.EL.getMousePosition(); //当前处理的鼠标位置
//        _UME["X"] = Math.min(Math.max(-_UW[0], _UME["X"] - _UE["X"]), _UW[1]); _UDVD.css("width", _UW[0] + _UME["X"] + "px"); _UDND.css("width", _UW[1] + _UME["X"] + "px"); //拖动大小处理
//        if (this.scb) { this.scb() }; //拖动回调
//    },
//    //拖动菜单
//    dragB: function () {
//        var _UW,
//        _UDPD = this.UDPD, //上级元素
//        _UDSD = this.prev, //上级元素
//        _UPW = this.pw, //总长度
//        _UW = this.uw[0], //上面兄弟节点的长度
//        _UE = this.UE, //鼠标的位置
//        _UME = U.UF.EL.getMousePosition(); //鼠标位置
//        _UME["X"] = Math.max(-_UW, _UME["X"] - _UE["X"]); //获取left
//        _UDSD.css("width", _UW + _UME["X"] + "px"); //设置下级兄弟的长度
//        _UDPD.css("width", (_UW = (_UME["X"] + this.w)) > this.pw ? _UW + "px" : this.pw + "px"); //设置上级兄弟的长度
//        if (this.scb) { this.scb() };
//    },
//    //拖动释放
//    up: function () {
//        this.el.releaseCapture(); //释放聚焦
//        U.selectEl(document.body).unbind({ "mousemove": this.move, "mouseup": this.mup }); //释放拖动绑定
//        if (this.upcb) { this.upcb() }; //回调处理
//    }
//}
//#endregion
;
///<jscompress sourcefile="MainStart.js" />
/*
1、检查UC里面还有没有自执行的函数。有的话添加此文件
2、重新归类整理所有的UC文件。主要的问题很多函数都是用U.UF.M的命名空间。每个文件开头要描述此文件是做什么的?
*/
U.UF.C.start = function () {
    //加载String数据类型
    U.UF.EV.addPrototype(String, U.UF.C.String);
    //加载Number数据类型
    U.UF.EV.addPrototype(Number, U.UF.C.Number);
    //加载Array数据类型
    U.UF.EV.addPrototype(Array, U.UF.C.Array);
    //JSON方法的兼容
    U.Json.init()
    //生成系统兼容处理,兼容ie6以上,firefox,safiry,chrome
    U.UF.CP.init();
    //ArrayBuffer兼容处理
    U.UF.S.ArrayBuffer();
    //基础控件加载
    //U.UF.C.loadControls();
    //手机端处理
    //touch事件的处理方式
    if ("ontouchstart" in document) {
        U.UF.CP.touch();
    }
}

/*
* 基础控件加载
*
*/
U.UF.C.loadControls = function () {
    var _allscript = U.selectEl("script"), //获取页面上所有script标签
            _flag = true, //用于设置是否需要引入基础控件,如果用户引入了全部控件,那么这个值为false。这个变量用于判断是否不再需要引入基础控件
            i; //用户循环
    //使用U.UF.CI.getUserPort()判断用户客户端是否为电脑端控件还是手机端。如果是电脑端,引入电脑端控件
    if (U.UF.CI.getUserPort()) {
        //循环页面上所有的script标签
        for (i = 0; i < _allscript.length; i++) {
            //如果是复杂控件的话,那么引入复杂控件js和css文件
            if ($(_allscript)[i].src == "http://www.1473.cn/uform.js" && U.selectEl(_allscript).attr("include") === "complex") {
                U.UF.DL.asynLoadJs({ type: "text/javascript", src: "http://www.1473.cn/js/Controls/Complex.js" });
                U.UF.DL.asynLoadCss({ "href": "http://www.1473.cn/css/Controls/Complex.css", type: "text/css", rel: "stylesheet" });
            }
            //如果是全部控件的话,那么引入全部控件的js和css文件
            if ($(_allscript)[i].src == "http://www.1473.cn/uform.js" && U.selectEl(_allscript).attr("include") === "all") {
                U.UF.DL.asynLoadJs({ type: "text/javascript", src: "http://www.1473.cn/js/Controls/index.js" });
                U.UF.DL.asynLoadCss({ "href": "http://www.1473.cn/css/Controls/index.css", type: "text/css", rel: "stylesheet" });
                _flag = false; //设置基础控件变量为false,因为引入了全部的控件,已经不需要再次引入基础控件了。
            }
        }
        //如果引入了全部的控件,那么该变量的值会为false。
        if (_flag) {
            U.UF.DL.asynLoadJs({ type: "text/javascript", src: "http://www.1473.cn/js/Controls/Basic.js" });
            U.UF.DL.asynLoadCss({ "href": "http://www.1473.cn/css/Controls/Basic.css", type: "text/css", rel: "stylesheet" });
        }
    }
    //如果是手机端控件,引入手机端的控件
    else {
        //循环页面上所有的script标签
        for (i = 0; i < _allscript.length; i++) {
            //如果是复杂控件的话,那么引入复杂控件js和css文件
            if ($(_allscript)[i].src == "http://www.1473.cn/uform.js" && U.selectEl(_allscript).attr("include") === "mtcomplex") {
                U.UF.DL.asynLoadJs({ type: "text/javascript", src: "http://m.1473.cn/Js/Controls/Complex.js" });
                U.UF.DL.asynLoadCss({ "href": "http://m.1473.cn/Css/Controls/Complex.css", type: "text/css", rel: "stylesheet" });
            }
            //如果是全部控件的话,那么引入全部控件的js和css文件
            if ($(_allscript)[i].src == "http://www.1473.cn/uform.js" && U.selectEl(_allscript).attr("include") === "mtall") {
                U.UF.DL.asynLoadJs({ type: "text/javascript", src: "http://m.1473.cn/Js/Controls/index.js" });
                U.UF.DL.asynLoadCss({ "href": "http://m.1473.cn/Css/Controls/index.css", type: "text/css", rel: "stylesheet" });
                _flag = false; //设置基础控件变量为false,因为引入了全部的控件,已经不需要再次引入基础控件了。
            }
        }
        //如果引入了全部的控件,那么该变量的值会为false。
        if (_flag) {
            U.UF.DL.asynLoadJs({ type: "text/javascript", src: "http://m.1473.cn/Js/Controls/Basic.js" });
            U.UF.DL.asynLoadCss({ "href": "http://m.1473.cn/Css/Controls/Basic.css", type: "text/css", rel: "stylesheet" });
        }
    }
}
U.UF.C.start(); //执行;
///<jscompress sourcefile="Login.js" />
Namespace.register("U.MD.U.L"); //用户登录的命名空间
Namespace.register("U.MD.U.LO"); //用户登出的命名空间

//#region 登录
/*
问题:
1、验证码的接口问题
2、无窗体的接口
*/

//#region 配置数据

U.MD.U.L.loginCallBack; //登录后的回调使用
U.MD.U.L.isLogining = false; //判断用户登录状态。cookie登录状态为cookie,账号登录为true,没有登录为false

//#endregion

/**
* 弹出登录注册
*
* @param  {int} type==3:登录页面,type==1:注册页面,type==2:找回密码页面
* @param  {function} cb为回调函数
* @returns {boolean} 是否登录
*/
U.MD.U.L.login = U.MD.U.L.DLTC = function (fun) {
    var _iframe = U.selectEl("#U_MD_HomeC_Pop iframe")[0];
    if ($("#U_MD_HomeC_Pop")[0]) {
        U.UF.F.windowTopCenter($("#U_MD_HomeC_Pop")[0]);
        try {
            //登录有的其他回调,如,登陆后直接打开好友聊天等
            if (U.UF.C.isFunction(fun)) {
                U.MD.U.L.loginCallBack = fun; //回调处理
            }
            U.selectEl("input", _iframe.contentWindow.document)[0].focus();
            _iframe.contentWindow.U.MD.U.L.init();
        }
        catch (e) { }
    }
    else {
        var _iframe = $$("iframe", { "style": { "border": "0", "float": "left" }, "id": "UI_Login", "name": "UI_Login", "frameborder": "no", "border": "0", "scrolling ": "no", "width": "360px", "height": "480px", "src": US.MAINDOMAIN + "/Login.htm" });
        new U.UF.UI.form("", _iframe,
                 {
                     "id": "U_MD_HomeC_Pop",
                     "style": {
                         "width": "360px",
                         "height": "510px"
                     }
                 },
                 {
                     isdrag: false,
                     isstretching: false,
                     isenlarge: false,
                     isnarrow: false
                 });
        //跨域回调设置
        U.UF.DL.iframeLoad(_iframe, function () {
            //登录有的其他回调,如,登陆后直接打开好友聊天等
            if (U.UF.C.isFunction(fun)) {
                U.MD.U.L.loginCallBack = fun; //回调处理
            }
            _iframe.contentWindow.U.MD.U.L.loginCallBack = U.MD.U.L.defaultCallBack; //设置登录回调
        });
    }
    return _iframe;
}

/** 
* 打开注册窗体
*/
U.MD.U.L.register = function (fun) {
    var _iframe = U.MD.U.L.login();
    try {
        _iframe.contentWindow.U.MD.U.R.register();
    }
    catch (e) {
        U.UF.DL.iframeLoad(_iframe, function () {
            //登录有的其他回调,如,登陆后直接打开好友聊天等
            if (U.UF.C.isFunction(fun)) {
                U.MD.U.L.loginCallBack = fun; //回调处理
            }
            _iframe.contentWindow.U.MD.U.L.loginCallBack = U.MD.U.L.defaultCallBack; //设置登录回调
            _iframe.contentWindow.U.UF.N.addHash('register'); //添加hash的处理
        });
    }
}

/** 
* 打开找回密码窗体
*/
U.MD.U.L.retrieve = function () {
    var _iframe = U.MD.U.L.login();
    try {
        _iframe.contentWindow.U.MD.U.F.findPassword();
    }
    catch (e) {
        U.UF.DL.iframeLoad(_iframe, function () {
            _iframe.contentWindow.U.UF.N.addHash('findPassword'); //添加hash的处理
        });
    }
}

/**
* 登录异步
*
* @param  {object} 服务器返回的值
* @param  {boolean} 是否是cookie登录
*/
U.MD.U.L.defaultCallBack = function (r, iscookie) {
    var _userinfo, //用户个人信息 
        _backgroudimage, //背景图片
        _str, //输出的提示
        _context = r.context, //回调参数
        _address = _context[1], //触发函数的地址
        _username = _context[2], //用户名
        _password = _context[3]; //密码
    //登录后台返回的数据
    r = r.value;
    //判断登录状态
    switch (r) {
        case null:
            _str = "系统繁忙!请重试";
            break; //系统繁忙
        case 0:
            _str = "帐号不存在!";
            break;
        case 1:
            _str = "密码错误!";
            break; //帐号密码错误
        case 2:
            _str = "该用户不允许被访问!请联系管理员";
            break; //用户给禁用
        default:
            if (r) {
                //登录有的其他回调,如,登陆后直接打开好友聊天等
                U.MD.U.LO.emptyUserInfo(); //登陆的时候先清空用户信息,防止前面登陆用户的信息有冲突
                //如果刚刚登陆的时候没有用户的地址,这里重新获取,然后向后台发送
                if (!_address) {
                    U.UF.CI.getUserLocation(U.MD.U.L.addUserAccess); //客户端信息加载,好像只加载了新浪ip地址?
                }
                _userinfo = U.MD.U.L.setUserInfo(r); //设置用户基本信息,包括用户信息,好友信息
                U.MD.U.L.getLoginUserInfo(_username || US.userInfo.UserName); //去获取用户详细信息
                if ($("#U_MD_D_BDI")[0] && U.selectEl('#U_MD_D_BG')[0]) {
                    //登录有用户的信息展示到页面中,包括背景图片、用户头像等
                    U.MD.U.L.printUserInfo(); //用户头部头像个人信息
                    _backgroudimage = U.MD.D.B.split(US.userInfo.UserBackGroundImage); //拆分用户的背景图片,里面包含了图片地址和展示的格式
                    U.MD.D.B.setBackgroundImage(_backgroudimage[0], _backgroudimage[1]); //设置用户背景图,以后需修改为设置用户桌面信息
                }
                //Cookie登录,即使密码错误也不弹出错误信息。
                if (_str && iscookie !== true) {
                    U.alert(_str); //登录提示处理
                }
                //如果弹出了登录框,那么给登录框进行处理
                if ($("#U_MD_HomeC_Pop")[0]) {
                    //登录框的样式还原
                    U.selectEl("#U_MD_HomeC_Pop")[0].close(); //关闭登陆款
                }

                U.MD.O && U.MD.O.P.connect();
            }
            //  _str = "登录成功";
    }
    if (_str) {
        U.alert(_str);
    }
}

/**
* 判断用户是否登录如果未登陆则弹出登陆框
*
*/
U.MD.U.L.isLogin = function (fun) {
    if (!US.userInfo.UserId) { //判断用户id是否存在
        U.MD.U.L.login(fun); //用户登录函数
        return true; //用户未登录返回false
    }
    return false; //用户登录返回true
}

/**
* 登录调用回调使用
* @param  {function} 回调函数
*
*/
U.MD.U.L.setLoginCallBack = function (fun) {
    //未登录要求登录
    if (U.MD.U.L.isLogin()) {
        U.MD.U.L.loginCallBack = fun;
    }
    //登录直接转发
    else {
        fun();
        return true;
    }
}


//#endregion

//#region cookie登录

/*
功能:1473.cn域下各个应用的用户通过Cookie自动登录,Cookie登录入口。支持跨域
*/
U.MD.U.L.cookieLogin = function () {
    var _cookie = U.MD.U.L.getCookieByUserId(), //获取用户的云端Cookie,选取最后一个账号进行登录。
        _address = US.city.userAllLocation || ""; //找到自己登陆用户的地址
    //如果获取到cookie的值,那么就进行cookie登陆
    if (_cookie && _cookie.userid && _cookie.userid.length == 36) {
        U.MD.U.L.isLogining = "cookie"; //设置cookie登陆状态
        U.A.Request(US.USER, ["LoginByCookie", _cookie.userid, _cookie.username], U.MD.U.L.defaultCallBack, ["", _address]); //调用cookie登陆处理
    }
}


/*
功能:获取用户cookie,云端cookie关键字为usestudiosso,格式为
Loginid:登录id
userstamp:账号13928417148的值为"1364812396"?奇怪?
userid:云端用户id
username:云端用户名
如果不传入参数,默认获取最后一个,否则获取传入userid的账号进行登录。
参数一:userid代表用户id。传入用户id,则判断cookie中是否有该账号,并使用该账号登录。
*/
U.MD.U.L.getCookieByUserId = function (userid) {
    var i, _cookiearr = U.MD.U.L.cookieToArray("usestudiosso"); //获取保存的cookie值。
    //如果传入参数userid并且cookie中有userid。则判断是否是自己的账号登录。
    if (_cookiearr.userid) {
        //如果传了userid,那么就根据userid找
        if (userid) {
            //数组里匹配
            for (i = 0; i < _cookiearr.userid.length; i++) {
                if (_cookiearr.userid[i] == userid) {
                    break;
                }
            }
        }
        //否则找到最后一个登陆用户的信息
        else {
            //允许多用户登录,则用户id减少一?
            i = _cookiearr.userid.length - 1;
        }
        //循环所有Cookie。
        for (var c in _cookiearr) {
            //对中文进行解密。_cookiearr[c]中可能有多个userid,只获取最后选中的第i个。返回的数据在这里做了处理。
            _cookiearr[c] = decodeURIComponent(_cookiearr[c][i]);
        }
    }
    //返回的集合包括了Loginid:登录iduserstamp:账号13928417148的值为"1364812396"?奇怪?userid:云端用户idusername:云端用户名
    return _cookiearr;
}

/**
*1473cookie格式专用
* 把形如:"userid=72854d28-f45c-48d7-92b7-3cd933e03022&username=13928417148&Loginid=fd02976d-993b-4437-bbd9-5efa99802c8f&userstamp=1364812396"的cookie转换为json对象。函数名有问题。
得到的形式为:_UAE.Loginid可得到用户id。
*
* @param  {string} 获取cookie的key对应的值 如usestudio=aa=ff&ss=aa 的usestudio里的 aa=ff&ss=aa
* @return  {object} {key:[value1,value2]}
*/
U.MD.U.L.cookieToArray = function (key) { //获取cookie
    var i, //循环初始化
        _cookieobj = {}, //初始化对象 作为返回值
    _cookie = U.UF.Cookie.get("usestudiosso"); //获取用户指定的Cookie值
    if (_cookie) { //是否存在
        _cookie = _cookie.split("&");
        for (i = 0; i < _cookie.length; i++) { //循环对应的值
            _cookie[i] = _cookie[i].split("="); //切分key和value
            //如果定义了cookie值的接受数组,则不再重复定义。_cookie[i][0]相当于key,例如userid
            if (!_cookieobj[_cookie[i][0]]) {
                _cookieobj[_cookie[i][0]] = [];
            }
            _cookieobj[_cookie[i][0]].push(decodeURIComponent(_cookie[i][1])); //生成{key:[value1,value2]}
        }
    }
    return _cookieobj;
}

//#endregion

//#region 登录数据使用

/**
* 为了以后的扩展,给其他系统获取完整的用户信息,获取用户登录数据,后面还有一个登陆获取用户个人信息。好友信息,及消息通知,逻辑有问题。
* @param  {string} 用户名
*
*/
U.MD.U.L.getLoginUserInfo = function (username) {
    U.A.Request(US.USER, ["GetUserLoginData", username], U.MD.U.L.asynGetLoginUserInfo);
}

/**
* 异步获取数据
* @param  {object} ajax返回的数据值
*
*/
U.MD.U.L.asynGetLoginUserInfo = function (r) {
    r = r.value; //得到登录用户的数据
    US.friend = r; //返回的r里面是用户的好友信息 包括  {"className":好友分组信息,friends:好友信息,group:好友群,groupusers:群好友,recentcontacts:最近联系人,unreadfirendmessage:未读好友消息,unreadgroupmessage:未读群消息,commonfriend:推荐好友}
    U.MD.U.L.initUserLogin(US.userInfo); //登录初始化应用
    if (U.MD.D && U.MD.D.IsUseStudio || U.selectEl("#usestudio_server")[0]) {
        U.MD.F && U.MD.F.N.friendMessageHandle([r.unreadfirendmessage, r.unreadgroupmessage]); //用户消息区域
    }
}

/**
* 添加用户初始化资料信息
* @param  {array} 登录用户的数据
*
*/
U.MD.U.L.setUserInfo = function (userinfo) {
    US.userInfo = userinfo[0]; //给用户信息全局变量赋值。
    US.userInfo.LoginId = userinfo[2]; //用户前后台更新数据唯一识别id
    US.friend.onlinefirendinfo = userinfo[1]; //添加在线信息。
    return US.userInfo;
}

//登录成功执行事件
U.MD.U.L.initUserLogin = function () {
    var _userinfo = US.userInfo; //初始化用户资料
    U.MD.UI && U.MD.UI.flashEmptyUpload && U.MD.UI.flashEmptyUpload(); //清理上传文件

    //登录有的其他回调,如,登陆后直接打开好友聊天等
    if (U.UF.C.isFunction(U.MD.U.L.loginCallBack)) {
        U.MD.U.L.loginCallBack(_userinfo); //回调处理
    }

    U.MD.F && U.MD.F.initFriend(); //初始化好友
    //如果没有用url指引,同时又是1473的项目,那么弹出云盘,否则只是加载数据
    if (U.MD.D && U.MD.D.IsUseStudio) {
        U.MD.D.I.openApplication("disk", { "userid": _userinfo.UserId, "directoryid": US.FTPFOLDERID }); //弹出云盘的数据。
    }


    //外部加载1473框架的都会带有usestudio_server 这个元素,当用户没有填写邮箱信息的时候,同时是在1473主站点的,那么就弹出用户
    if (!US.userInfo.UserEmail && !$("#usestudio_server")[0]) {
        U.MD.U.P.userDataSet(); //用户数据加载
    }
}


/**
* 添加用户登录信息
*
*/
U.MD.U.L.addUserAccess = function () {
    //如果用户的城市信息不存在,则添加用户用户城市信息,应该不只是单单判断地址,此处逻辑还需要整理!
    if (US.city.userAllLocation) {
        U.A.Request(US.USER, ["RecordUserClientInfo", US.userInfo.UserName, "", "", US.city.userAllLocation, ""],
                    function () { }); //异步添加地址信息
    }
}

/**
* 打印用户的信息
*
*/
U.MD.U.L.printUserInfo = function () {
    var _childel,
        _userinfo = US.userInfo, //用户的信息
        _userimage = U.MD.C.getHeadImage(_userinfo.UserThumbnailImageHead), //获取用户头像
        _el = U.selectEl("#U_MD_D_BDI"); //头像打印的区域
    if (_el[0]) {
        //设置头部的样式变化
        _el.addAttrArray({
            "className": "U_MD_D_BDI"
        })[0];
        //如果已经有头像了,那么直接修改头像
        if (_el.find("img")[0]) {
            //设置头像处理
            _el.find("img").addAttrArray({
                "onerror": U.MD.C.imgError,
                "title": _userinfo.UserNickName,
                "onclick": function () {
                    U.MD.D.I.openApplication("set");
                },
                "src": U.MD.C.getHeadImage(_userinfo.UserThumbnailImageHead)
            });
        }
        //创建头像的处理
        else {
            $$("img", { "onerror": U.MD.C.imgError,
                "onerror": U.MD.C.imgError,
                "title": _userinfo.UserNickName,
                "onclick": function () {
                    U.MD.D.I.openApplication("set");
                },
                "src": U.MD.C.getHeadImage(_userinfo.UserThumbnailImageHead)
            }, _el[0])
        }
        _childel = U.selectEl("#U_MD_D_BDL").Child();
        _childel[0].style.display = _childel[1].style.display = "none";
        _childel[2].style.display = "block";
    }
}

//#endregion

//#region 退出

/**
* 退出登录提示
*
* @param callback {function} 登出回调函数
*/
U.MD.U.LO.logoutSystem = function (callback) {
    //如果用户登录的情况
    if (US.userInfo.UserId) {
        //弹出退出登录的提示
        U.UF.UI.confirm("是否退出" + US.userInfo.UserName + "账号", function () {
            U.MD.U.LO.logout(callback);
        });
    }
}

//确定注销
//b为是否清除cookie的参数。如果传递false,则清除cookie。

/**
* 退出登录的处理
*
*/
U.MD.U.LO.logout = function (callback) {
    //    if (U.MD.O) {
    //        //获取office内容
    //        // U.A.Request(US.SCOKET, ['logout', US.userInfo.UserId, US.pageId], function () { });
    //    }
    U.MD.U.LO.clearCookie(function () {
        U.MD.U.LO.emptyUserInfo(); //清楚用户的前端的数据
        if ($('#UI_Login')[0]) {
            U.selectEl('#UI_Login')[0].contentWindow.U.MD.U.OT.logout(); //如果是第三方平台登录的,在第三方平台进行下线
        }
        //清理图形界面的处理
        if ($("#U_MD_D_BDI")[0]) {
            //清空所有的应用
            U.MD.U.LO.logoutStyle(); //清除注册样式
            U.MD.D.T.taskbar.clear(); //任务栏清除
            U.UF.UI.form.closeWindows(); //关闭所有的窗体
        }
        U.UF.C.isFunction(callback) && callback();
    }); //退出账号的cookie
}

/**
* 用户退出指定帐号 清理cookie
*
*/
U.MD.U.LO.clearCookie = function (callback) {
    //判断用户是否登录
    if (US.userInfo.UserId) {
        var _iscookie = U.UF.Cookie.get("usestudiosso", "userid").indexOf(US.userInfo.UserId) > -1; //判断cookie是否还存在用户的id
        //如果存在cookie的出力
        if (_iscookie) {
            //调用后台,让用户注销
            U.A.Request(US.USER, ["UserOffline", US.userInfo.UserId], function () { U.UF.C.isFunction(callback) && callback(); });
        } else {
            U.UF.C.isFunction(callback) && callback();
        }
    }
}

/**
* 清空用户前端的信息
*
*/
U.MD.U.LO.emptyUserInfo = function () {
    US.userInfo = {}; //用户数据清空
    US.friend = {}; //用户好友信息清空
    if ($("#U_MD_D_BG")[0]) {
        U.MD.D.B.setBackgroundImage(U.MD.D.B.url); //设置默认背景
    }
}


/**
* 注销样式
*
*/
U.MD.U.LO.logoutStyle = function () {
    //清楚登录用户的样式
    U.selectEl("#U_MD_D_BDI").addAttrArray({
        "innerHTML": "",
        "className": "U_MD_D_BDI U_Img"
    });
    //获取子元素
    var _childel = U.selectEl("#U_MD_D_BDL").childs();
    _childel[0].style.display = _childel[1].style.display = "block"; //显示登录注册
    _childel[2].style.display = "none";  //隐藏提出按钮
    //右边好友框隐藏
    U.selectEl("#U_MD_F_H_R").css("display", "none");
    //隐藏消息提醒
    U.selectEl("#U_MD_D_MG_OA").Parent(2).style.display = "none";
    //隐藏所有的窗体
    //   U.selectEl("#U_MD_Home").childs().css("display", "none");
}

//#endregion

//#region 外链登录
Namespace.register("U.MD.U.OT"); //用户登录的命名空间

/**
* 填写登录信息
*
* @param  {array} 登录值参数
* @param  {array} 回调函数
*/
U.MD.U.OT.perfectUserInfo = function (userinfo, username) {
    if ($("#U_MD_U_OT_B_Pop")[0]) {
        U.UF.F.windowTopCenter($("#U_MD_U_OT_B_Pop")[0]);
    }
    else {
        var _iframe = $$("iframe", { "style": { "border": "0", "float": "left" }, "id": "U_MD_U_OT_B_Iframe", "name": "UI_Login", "frameborder": "0", "width": "400px", "height": "290px", "src": US.MAINDOMAIN + "/CompleteInformation.htm" });
        new U.UF.UI.form("", _iframe,
                 {
                     "id": "U_MD_U_OT_B_Pop",
                     "style": {
                         "width": "400px",
                         "height": "340px"
                     }
                 },
                 {
                     isdrag: false,
                     isstretching: false,
                     isenlarge: false,
                     isnarrow: false
                 });
        //跨域回调设置
        U.UF.DL.iframeLoad(_iframe, function () {
            if ($("#U_MD_HomeC_Pop")[0]) {
                U.selectEl("#U_MD_HomeC_Pop")[0].close();
            }
            _iframe.contentWindow.U.MD.U.OT.perfectUserInfoInit(userinfo, username); //设置登录回调
        });
    }
}
//#endregion
;
///<jscompress sourcefile="Encrypted.js" />
//#region 加密区域

Namespace.register("U.UF.EC"); //加密

/*
* Fastest md5 implementation around (JKM md5).
* Credits: Joseph Myers
*
* @see http://www.myersdaily.org/joseph/javascript/md5-text.html
* @see http://jsperf.com/md5-shootout/7
*/
/* this function is much faster,
so if possible we use it. Some IEs
are the only ones I know of that
need the idiotic second function,
generated by an if clause.  */
U.UF.EC.add32 = function (a, b) {
    return (a + b) & 0xFFFFFFFF;
};

U.UF.EC.hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];

U.UF.EC.cmn = function (q, a, b, x, s, t) {
    a = U.UF.EC.add32(U.UF.EC.add32(a, q), U.UF.EC.add32(x, t));
    return U.UF.EC.add32((a << s) | (a >>> (32 - s)), b);
}

U.UF.EC.md5cycle = function (x, k) {
    var a = x[0],
            b = x[1],
            c = x[2],
            d = x[3];

    a += (b & c | ~b & d) + k[0] - 680876936 | 0;
    a = (a << 7 | a >>> 25) + b | 0;
    d += (a & b | ~a & c) + k[1] - 389564586 | 0;
    d = (d << 12 | d >>> 20) + a | 0;
    c += (d & a | ~d & b) + k[2] + 606105819 | 0;
    c = (c << 17 | c >>> 15) + d | 0;
    b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
    b = (b << 22 | b >>> 10) + c | 0;
    a += (b & c | ~b & d) + k[4] - 176418897 | 0;
    a = (a << 7 | a >>> 25) + b | 0;
    d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
    d = (d << 12 | d >>> 20) + a | 0;
    c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
    c = (c << 17 | c >>> 15) + d | 0;
    b += (c & d | ~c & a) + k[7] - 45705983 | 0;
    b = (b << 22 | b >>> 10) + c | 0;
    a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
    a = (a << 7 | a >>> 25) + b | 0;
    d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
    d = (d << 12 | d >>> 20) + a | 0;
    c += (d & a | ~d & b) + k[10] - 42063 | 0;
    c = (c << 17 | c >>> 15) + d | 0;
    b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
    b = (b << 22 | b >>> 10) + c | 0;
    a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
    a = (a << 7 | a >>> 25) + b | 0;
    d += (a & b | ~a & c) + k[13] - 40341101 | 0;
    d = (d << 12 | d >>> 20) + a | 0;
    c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
    c = (c << 17 | c >>> 15) + d | 0;
    b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
    b = (b << 22 | b >>> 10) + c | 0;

    a += (b & d | c & ~d) + k[1] - 165796510 | 0;
    a = (a << 5 | a >>> 27) + b | 0;
    d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
    d = (d << 9 | d >>> 23) + a | 0;
    c += (d & b | a & ~b) + k[11] + 643717713 | 0;
    c = (c << 14 | c >>> 18) + d | 0;
    b += (c & a | d & ~a) + k[0] - 373897302 | 0;
    b = (b << 20 | b >>> 12) + c | 0;
    a += (b & d | c & ~d) + k[5] - 701558691 | 0;
    a = (a << 5 | a >>> 27) + b | 0;
    d += (a & c | b & ~c) + k[10] + 38016083 | 0;
    d = (d << 9 | d >>> 23) + a | 0;
    c += (d & b | a & ~b) + k[15] - 660478335 | 0;
    c = (c << 14 | c >>> 18) + d | 0;
    b += (c & a | d & ~a) + k[4] - 405537848 | 0;
    b = (b << 20 | b >>> 12) + c | 0;
    a += (b & d | c & ~d) + k[9] + 568446438 | 0;
    a = (a << 5 | a >>> 27) + b | 0;
    d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
    d = (d << 9 | d >>> 23) + a | 0;
    c += (d & b | a & ~b) + k[3] - 187363961 | 0;
    c = (c << 14 | c >>> 18) + d | 0;
    b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
    b = (b << 20 | b >>> 12) + c | 0;
    a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
    a = (a << 5 | a >>> 27) + b | 0;
    d += (a & c | b & ~c) + k[2] - 51403784 | 0;
    d = (d << 9 | d >>> 23) + a | 0;
    c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
    c = (c << 14 | c >>> 18) + d | 0;
    b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
    b = (b << 20 | b >>> 12) + c | 0;

    a += (b ^ c ^ d) + k[5] - 378558 | 0;
    a = (a << 4 | a >>> 28) + b | 0;
    d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
    d = (d << 11 | d >>> 21) + a | 0;
    c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
    c = (c << 16 | c >>> 16) + d | 0;
    b += (c ^ d ^ a) + k[14] - 35309556 | 0;
    b = (b << 23 | b >>> 9) + c | 0;
    a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
    a = (a << 4 | a >>> 28) + b | 0;
    d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
    d = (d << 11 | d >>> 21) + a | 0;
    c += (d ^ a ^ b) + k[7] - 155497632 | 0;
    c = (c << 16 | c >>> 16) + d | 0;
    b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
    b = (b << 23 | b >>> 9) + c | 0;
    a += (b ^ c ^ d) + k[13] + 681279174 | 0;
    a = (a << 4 | a >>> 28) + b | 0;
    d += (a ^ b ^ c) + k[0] - 358537222 | 0;
    d = (d << 11 | d >>> 21) + a | 0;
    c += (d ^ a ^ b) + k[3] - 722521979 | 0;
    c = (c << 16 | c >>> 16) + d | 0;
    b += (c ^ d ^ a) + k[6] + 76029189 | 0;
    b = (b << 23 | b >>> 9) + c | 0;
    a += (b ^ c ^ d) + k[9] - 640364487 | 0;
    a = (a << 4 | a >>> 28) + b | 0;
    d += (a ^ b ^ c) + k[12] - 421815835 | 0;
    d = (d << 11 | d >>> 21) + a | 0;
    c += (d ^ a ^ b) + k[15] + 530742520 | 0;
    c = (c << 16 | c >>> 16) + d | 0;
    b += (c ^ d ^ a) + k[2] - 995338651 | 0;
    b = (b << 23 | b >>> 9) + c | 0;

    a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
    a = (a << 6 | a >>> 26) + b | 0;
    d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
    d = (d << 10 | d >>> 22) + a | 0;
    c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
    c = (c << 15 | c >>> 17) + d | 0;
    b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
    b = (b << 21 | b >>> 11) + c | 0;
    a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
    a = (a << 6 | a >>> 26) + b | 0;
    d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
    d = (d << 10 | d >>> 22) + a | 0;
    c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
    c = (c << 15 | c >>> 17) + d | 0;
    b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
    b = (b << 21 | b >>> 11) + c | 0;
    a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
    a = (a << 6 | a >>> 26) + b | 0;
    d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
    d = (d << 10 | d >>> 22) + a | 0;
    c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
    c = (c << 15 | c >>> 17) + d | 0;
    b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
    b = (b << 21 | b >>> 11) + c | 0;
    a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
    a = (a << 6 | a >>> 26) + b | 0;
    d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
    d = (d << 10 | d >>> 22) + a | 0;
    c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
    c = (c << 15 | c >>> 17) + d | 0;
    b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
    b = (b << 21 | b >>> 11) + c | 0;

    x[0] = a + x[0] | 0;
    x[1] = b + x[1] | 0;
    x[2] = c + x[2] | 0;
    x[3] = d + x[3] | 0;
}

U.UF.EC.md5blk = function (s) {
    var md5blks = [],
            i; /* Andy King said do it this way. */

    for (i = 0; i < 64; i += 4) {
        md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
    }
    return md5blks;
}

U.UF.EC.md5blk_array = function (a) {
    var md5blks = [],
            i; /* Andy King said do it this way. */

    for (i = 0; i < 64; i += 4) {
        md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
    }
    return md5blks;
}

U.UF.EC.md51 = function (s) {
    var n = s.length,
            state = [1732584193, -271733879, -1732584194, 271733878],
            i,
            length,
            tail,
            tmp,
            lo,
            hi;

    for (i = 64; i <= n; i += 64) {
        U.UF.EC.md5cycle(state, U.UF.EC.md5blk(s.substring(i - 64, i)));
    }
    s = s.substring(i - 64);
    length = s.length;
    tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    for (i = 0; i < length; i += 1) {
        tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
    }
    tail[i >> 2] |= 0x80 << ((i % 4) << 3);
    if (i > 55) {
        U.UF.EC.md5cycle(state, tail);
        for (i = 0; i < 16; i += 1) {
            tail[i] = 0;
        }
    }

    // Beware that the final length might not fit in 32 bits so we take care of that
    tmp = n * 8;
    tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
    lo = parseInt(tmp[2], 16);
    hi = parseInt(tmp[1], 16) || 0;

    tail[14] = lo;
    tail[15] = hi;

    U.UF.EC.md5cycle(state, tail);
    return state;
}

U.UF.EC.md51_array = function (a) {
    var n = a.length,
            state = [1732584193, -271733879, -1732584194, 271733878],
            i,
            length,
            tail,
            tmp,
            lo,
            hi;

    for (i = 64; i <= n; i += 64) {
        U.UF.EC.md5cycle(state, U.UF.EC.md5blk_array(a.subarray(i - 64, i)));
    }

    // Not sure if it is a bug, however IE10 will always produce a sub array of length 1
    // containing the last element of the parent array if the sub array specified starts
    // beyond the length of the parent array - weird.
    // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
    a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);

    length = a.length;
    tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    for (i = 0; i < length; i += 1) {
        tail[i >> 2] |= a[i] << ((i % 4) << 3);
    }

    tail[i >> 2] |= 0x80 << ((i % 4) << 3);
    if (i > 55) {
        U.UF.EC.md5cycle(state, tail);
        for (i = 0; i < 16; i += 1) {
            tail[i] = 0;
        }
    }

    // Beware that the final length might not fit in 32 bits so we take care of that
    tmp = n * 8;
    tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
    lo = parseInt(tmp[2], 16);
    hi = parseInt(tmp[1], 16) || 0;

    tail[14] = lo;
    tail[15] = hi;

    U.UF.EC.md5cycle(state, tail);

    return state;
}

U.UF.EC.rhex = function (n) {
    var s = '',
            j;
    for (j = 0; j < 4; j += 1) {
        s += U.UF.EC.hex_chr[(n >> (j * 8 + 4)) & 0x0F] + U.UF.EC.hex_chr[(n >> (j * 8)) & 0x0F];
    }
    return s;
}

U.UF.EC.hex = function (x) {
    var i;
    for (i = 0; i < x.length; i += 1) {
        x[i] = U.UF.EC.rhex(x[i]);
    }
    return x.join('');
}
//此处需要预先执行?
// In some cases the fast U.UF.EC.add32 function cannot be used..
/*if (U.UF.EC.hex(U.UF.EC.md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') {
U.UF.EC.add32 = function (x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF),
msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
};
}*/

// ---------------------------------------------------

// ---------------------------------------------------

/**
* Helpers.
*/
U.UF.EC.toUtf8 = function (str) {
    if (/[\u0080-\uFFFF]/.test(str)) {
        str = unescape(encodeURIComponent(str));
    }

    return str;
}

U.UF.EC.utf8Str2ArrayBuffer = function (str, returnUInt8Array) {
    var length = str.length,
           buff = new ArrayBuffer(length),
           arr = new Uint8Array(buff),
           i;

    for (i = 0; i < length; i += 1) {
        arr[i] = str.charCodeAt(i);
    }

    return returnUInt8Array ? arr : buff;
}

U.UF.EC.arrayBuffer2Utf8Str = function (buff) {
    return String.fromCharCode.apply(null, new Uint8Array(buff));
}

U.UF.EC.concatenateArrayBuffers = function (first, second, returnUInt8Array) {
    var result = new Uint8Array(first.byteLength + second.byteLength);

    result.set(new Uint8Array(first));
    result.set(new Uint8Array(second), first.byteLength);

    return returnUInt8Array ? result : result.buffer;
}

U.UF.EC.hexToBinaryString = function (hex) {
    var bytes = [],
            length = hex.length,
            x;

    for (x = 0; x < length - 1; x += 2) {
        bytes.push(parseInt(hex.substr(x, 2), 16));
    }

    return String.fromCharCode.apply(String, bytes);
}

// ---------------------------------------------------

/**
* U.UF.EC.SparkMD5 OOP implementation.
*
* Use this class to perform an incremental md5, otherwise use the
* static methods instead.
*/

U.UF.EC.SparkMD5 = function () {
    // call reset to init the instance
    this.reset();
}

/**
* Appends a string.
* A conversion will be applied if an utf8 string is detected.
*
* @param {String} str The string to be appended
*
* @return {U.UF.EC.SparkMD5} The instance itself
*/
U.UF.EC.SparkMD5.prototype.append = function (str) {
    // Converts the string to utf8 bytes if necessary
    // Then append as binary
    this.appendBinary(U.UF.EC.toUtf8(str));

    return this;
};

/**
* Appends a binary string.
*
* @param {String} contents The binary string to be appended
*
* @return {U.UF.EC.SparkMD5} The instance itself
*/
U.UF.EC.SparkMD5.prototype.appendBinary = function (contents) {
    this._buff += contents;
    this._length += contents.length;

    var length = this._buff.length,
            i;

    for (i = 64; i <= length; i += 64) {
        U.UF.EC.md5cycle(this._hash, U.UF.EC.md5blk(this._buff.substring(i - 64, i)));
    }

    this._buff = this._buff.substring(i - 64);

    return this;
};

/**
* Finishes the incremental computation, reseting the internal state and
* returning the result.
*
* @param {Boolean} raw True to get the raw string, false to get the U.UF.EC.hex string
*
* @return {String} The result
*/
U.UF.EC.SparkMD5.prototype.end = function (raw) {
    var buff = this._buff,
            length = buff.length,
            i,
            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            ret;

    for (i = 0; i < length; i += 1) {
        tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
    }

    this._finish(tail, length);
    ret = U.UF.EC.hex(this._hash);

    if (raw) {
        ret = U.UF.EC.hexToBinaryString(ret);
    }

    this.reset();

    return ret;
};

/**
* Resets the internal state of the computation.
*
* @return {U.UF.EC.SparkMD5} The instance itself
*/
U.UF.EC.SparkMD5.prototype.reset = function () {
    this._buff = '';
    this._length = 0;
    this._hash = [1732584193, -271733879, -1732584194, 271733878];

    return this;
};

/**
* Gets the internal state of the computation.
*
* @return {Object} The state
*/
U.UF.EC.SparkMD5.prototype.getState = function () {
    return {
        buff: this._buff,
        length: this._length,
        hash: this._hash
    };
};

/**
* Gets the internal state of the computation.
*
* @param {Object} state The state
*
* @return {U.UF.EC.SparkMD5} The instance itself
*/
U.UF.EC.SparkMD5.prototype.setState = function (state) {
    this._buff = state.buff;
    this._length = state.length;
    this._hash = state.hash;

    return this;
};

/**
* Releases memory used by the incremental buffer and other additional
* resources. If you plan to use the instance again, use reset instead.
*/
U.UF.EC.SparkMD5.prototype.destroy = function () {
    delete this._hash;
    delete this._buff;
    delete this._length;
};

/**
* Finish the final calculation based on the tail.
*
* @param {Array}  tail   The tail (will be modified)
* @param {Number} length The length of the remaining buffer
*/
U.UF.EC.SparkMD5.prototype._finish = function (tail, length) {
    var i = length,
            tmp,
            lo,
            hi;

    tail[i >> 2] |= 0x80 << ((i % 4) << 3);
    if (i > 55) {
        U.UF.EC.md5cycle(this._hash, tail);
        for (i = 0; i < 16; i += 1) {
            tail[i] = 0;
        }
    }

    // Do the final computation based on the tail and length
    // Beware that the final length may not fit in 32 bits so we take care of that
    tmp = this._length * 8;
    tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
    lo = parseInt(tmp[2], 16);
    hi = parseInt(tmp[1], 16) || 0;

    tail[14] = lo;
    tail[15] = hi;
    U.UF.EC.md5cycle(this._hash, tail);
};

/**
* Performs the md5 hash on a string.
* A conversion will be applied if utf8 string is detected.
*
* @param {String}  str The string
* @param {Boolean} [raw] True to get the raw string, false to get the U.UF.EC.hex string
*
* @return {String} The result
*/
U.UF.EC.SparkMD5.hash = function (str, raw) {
    // Converts the string to utf8 bytes if necessary
    // Then compute it using the binary function
    return U.UF.EC.SparkMD5.hashBinary(U.UF.EC.toUtf8(str), raw);
};

/**
* Performs the md5 hash on a binary string.
*
* @param {String}  content The binary string
* @param {Boolean} [raw]     True to get the raw string, false to get the U.UF.EC.hex string
*
* @return {String} The result
*/
U.UF.EC.SparkMD5.hashBinary = function (content, raw) {
    var hash = U.UF.EC.md51(content),
            ret = U.UF.EC.hex(hash);

    return raw ? U.UF.EC.hexToBinaryString(ret) : ret;
};

// ---------------------------------------------------

/**
* U.UF.EC.SparkMD5 OOP implementation for array buffers.
*
* Use this class to perform an incremental md5 ONLY for array buffers.
*/
U.UF.EC.SparkMD5.ArrayBuffer = function () {
    // call reset to init the instance
    this.reset();
};

/**
* Appends an array buffer.
*
* @param {ArrayBuffer} arr The array to be appended
*
* @return {U.UF.EC.SparkMD5.ArrayBuffer} The instance itself
*/
U.UF.EC.SparkMD5.ArrayBuffer.prototype.append = function (arr) {
    var buff = U.UF.EC.concatenateArrayBuffers(this._buff.buffer, arr, true),
            length = buff.length,
            i;

    this._length += arr.byteLength;

    for (i = 64; i <= length; i += 64) {
        U.UF.EC.md5cycle(this._hash, U.UF.EC.md5blk_array(buff.subarray(i - 64, i)));
    }

    this._buff = (i - 64) < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);

    return this;
};

/**
* Finishes the incremental computation, reseting the internal state and
* returning the result.
*
* @param {Boolean} raw True to get the raw string, false to get the U.UF.EC.hex string
*
* @return {String} The result
*/
U.UF.EC.SparkMD5.ArrayBuffer.prototype.end = function (raw) {
    var buff = this._buff,
            length = buff.length,
            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            i,
            ret;

    for (i = 0; i < length; i += 1) {
        tail[i >> 2] |= buff[i] << ((i % 4) << 3);
    }

    this._finish(tail, length);
    ret = U.UF.EC.hex(this._hash);

    if (raw) {
        ret = U.UF.EC.hexToBinaryString(ret);
    }

    this.reset();

    return ret;
};

/**
* Resets the internal state of the computation.
*
* @return {U.UF.EC.SparkMD5.ArrayBuffer} The instance itself
*/
U.UF.EC.SparkMD5.ArrayBuffer.prototype.reset = function () {
    this._buff = new Uint8Array(0);
    this._length = 0;
    this._hash = [1732584193, -271733879, -1732584194, 271733878];

    return this;
};

/**
* Gets the internal state of the computation.
*
* @return {Object} The state
*/
U.UF.EC.SparkMD5.ArrayBuffer.prototype.getState = function () {
    var state = U.UF.EC.SparkMD5.prototype.getState.call(this);

    // Convert buffer to a string
    state.buff = U.UF.EC.arrayBuffer2Utf8Str(state.buff);

    return state;
};

/**
* Gets the internal state of the computation.
*
* @param {Object} state The state
*
* @return {U.UF.EC.SparkMD5.ArrayBuffer} The instance itself
*/
U.UF.EC.SparkMD5.ArrayBuffer.prototype.setState = function (state) {
    // Convert string to buffer
    state.buff = U.UF.EC.utf8Str2ArrayBuffer(state.buff, true);

    return U.UF.EC.SparkMD5.prototype.setState.call(this, state);
};

U.UF.EC.SparkMD5.ArrayBuffer.prototype.destroy = U.UF.EC.SparkMD5.prototype.destroy;

U.UF.EC.SparkMD5.ArrayBuffer.prototype._finish = U.UF.EC.SparkMD5.prototype._finish;

/**
* Performs the md5 hash on an array buffer.
*
* @param {ArrayBuffer} arr The array buffer
* @param {Boolean}     [raw] True to get the raw string, false to get the U.UF.EC.hex one
*
* @return {String} The result
*/
U.UF.EC.SparkMD5.ArrayBuffer.hash = function (arr, raw) {
    var hash = U.UF.EC.md51_array(new Uint8Array(arr)),
            ret = U.UF.EC.hex(hash);

    return raw ? U.UF.EC.hexToBinaryString(ret) : ret;
};

//
//参数一:文件对象
//参数二:进度条回调
//参数三:文件计算md5完毕后的回调,回调函数中得到md5值。
U.UF.EC.MD5 = function (file, progressCb, cb) {
}
;
///<jscompress sourcefile="Api.js" />
Namespace.register("U.UF.API"); //第三方接口

/*
* 初始化用户系统
*
*/
U.UF.API.user = function () {
    U.UF.DL.asynLoadJs({ type: "text/javascript", charset: "utf8", async: true, src: "http://user.1473.cn/js/User.js" });
}

/*
* 初始化好友系统
*
*/
U.UF.API.friend = function () {
    U.UF.DL.asynLoadJs({ type: "text/javascript", charset: "utf8", async: true, src: "http://friend.1473.cn/js/Friend.js" });
}

/*
* 初始化
*
*/
U.UF.API.disk = function () {
    U.UF.DL.asynLoadJs({ type: "text/javascript", charset: "utf8", async: true, src: "http://disk.1473.cn/js/Disk.js" });
};
///<jscompress sourcefile="EditorTable.js" />
Namespace.register("U.UF.E");
//初始化table


/**
*  表格总接口
* range为编辑器的光标对象
*/
U.UF.E.table = function (range) {
    var _p,
        _inputo,
        _inputt,
        _frag = $$("frag"),
        _table = U.UF.E.table;  //简写命名空间
    _table._range = range;
    _p = $$("p", { "style": { "cssText": "text-align: left;font-weight: bold;padding: 10px 0 0 15px;" }, "innerHTML": "表格尺寸: " }, _frag);
    _p = $$("p", { "style": { "cssText": "text-align: left;margin-top: 15px;font-size: 14px;padding-left: 30px;" }, "innerHTML": "列数: " }, _frag);
    _inputo = $$("input", { "type": "number", "style": { "cssText": "width: 80px;margin-left: 65px;" }, "min": "1" }, _p);
    _p = $$("p", { "style": { "cssText": "text-align: left;padding-left: 30px;margin-top: 15px;font-size: 14px;margin-bottom: 22px;" }, "innerHTML": "行数: " }, _frag);
    _inputt = $$("input", { "type": "number", "style": { "cssText": "width: 80px;margin-left: 65px;" }, "min": "1" }, _p);
    //弹出框的html代码
    U.UF.UI.confirm(_frag, function () {    //弹框输入 行 和 列
        var _row = _inputo.value;   //行
        var _col = _inputt.value;   //列
        if (_row >= 1 && _col >= 1) {   //如果 行和列的值大于1 则添加表格
            _table.addTable(_row, _col);
        }
    });
    U.selectEl(document).unbind('mousedown', U.UF.E.table.removeFocus); //先取消事件监听 在添加 防止重复绑定
    U.selectEl(document).bind('mousedown', U.UF.E.table.removeFocus); //添加点击时的聚焦效果 并且若存在textarea元素 则删除并获取textarea的值给td
};

//初始化整理table,功能作用: 给外部添加的table元素添加样式和事件
U.UF.E.table.load = function (tableel) {
    var _table = U.UF.E.table;  //简写命名空间
    var _tableEl = tableel;
    if (_tableEl.features) return;  //如果已初始化 则直接返回

    _tableEl.features = true;   //代表已初始化过
    var _pelDiv = _tableEl.parentNode;  //父节点的初始化
    var _allTd = _tableEl.querySelectorAll("td");

    _allTd.forEach(function (v) {   /*删除所有display为none的dt元素*/
        U.selectEl(v).rmAttr("width");
        var _value = U.selectEl(v).css("display");
        if (_value === "none") {
            v.remove();
        }
    });

    _pelDiv.style.cssText = "overflow-y:hidden;padding-bottom:5px;padding-right:7px;";   //_div的样式
    _tableEl.style.cssText = _tableEl.style.cssText + "border-spacing: 0;border-collapse: collapse;position: relative;";
    _tableEl.contentEditable = "false";
    _table.tableOver(_tableEl);  //添加选中选出事件 防止选中td时 选中外面的元素 而报错
    var _trList = _tableEl.querySelectorAll("tr");
    var _tdList = U.selectEl(_tableEl).find("td");
    //列拉升处理
    for (var i = 0; i < _tdList.length; i++) {
        var _tdCopy = _tdList[i];
        _tdCopy.contentEditable = "true";
        _tdCopy.style.cssText += ";outline:0;box-sizing:border-box;position:relative;padding:0px;border:2px solid #333;" //这样子写csstext不会给覆盖
        var _tdWidth = _tdCopy.clientWidth;
        _tdCopy.style.width = _tdWidth + "px";    //给td添加width
        _table.loadCell(_tdCopy); //初始有合并单元格 的情况
        var _colRule = $$("div", { "style": { "outline": "0", "zIndex": "1", "position": "absolute", "top": 0, "right": 0, "cursor": "col-resize", "width": "3px", "height": "100%" }, "tabindex": "0", "contenteditable": "false", "className": "U_MD_O_W_Table_colRule", "inline": true }, _tdCopy); //列尺
        _table.colExpanding(_colRule); //给列尺 添加左右拉伸事件
        _table.dragCheckd(_tdCopy);    //td拖拽的选中事件
        _table.rightClick(_tableEl);    //添加右键
    }
    //行拉升处理
    for (var i = 0; i < _trList.length; i++) {
        var _trEl = _trList[i];
        _trEl.style.cssText += ";position:relative;overflow:hidden;";
        var _rowRule = $$("div", { "style": { "outline": "0", "zIndex": "1", "position": "absolute", "left": 0, "margin-top": _trEl.clientHeight + "px", cursor: "row-resize", height: "3px", width: "100%" }, tabindex: "0", "contenteditable": "false", "className": "U_MD_O_W_Table_rowRule", "inline": true }, _trEl); //行尺
        _table.rowExpanding(_rowRule);  //行尺 上下拉伸事件
    };
}

/**
* 初始有合并单元格 的情况
* tdEl td元素
*/
U.UF.E.table.loadCell = function (tdEl) {
    var _table = U.UF.E.table;  //简写命名空间
    var _tableEl = _table.parentSelect(tdEl, "table");   //获取table元素
    var _colSpan = tdEl.colSpan - 1;   //跨了_colSpan列
    var _rowSpan = tdEl.rowSpan - 1;  //跨了_rowSpan行
    if (_colSpan >= 1) {
        for (var i = 0; i < _colSpan; i++) {
            var _newTd = $$("td");
            _newTd.style.display = "none";
            _table.After(tdEl, _newTd);
        }
    }
    if (_rowSpan >= 1) {
        var _tdIndex = _table.index(tdEl);       //获取该td的所在索引
        var _trIndex = _table.index(tdEl.parentNode);  //获取该行tr所在位置
        var _trList = _tableEl.querySelectorAll("tr"); //获取所有的tr

        for (var i = 1; i <= _rowSpan; i++) {    //获取该tr的下_rowSpan个tr
            var _tdList = _trList[_trIndex + i].querySelectorAll("td"); //获取该tr的所有td
            var _td = _tdList[_tdIndex - 1];
            for (var j = 0; j <= _colSpan; j++) {
                var _newTd = $$("td");
                _newTd.style.display = "none";
                _table.After(_td, _newTd);
            }
        }
    }
}

/**
* 创建表格
* @param row   表格的行
* @param col   表格的列
*/
U.UF.E.table.addTable = function (row, col) {
    var i, j, _tr, _td,
        _frag = $$("frag"),
        _pel = U.UF.E.table.createTablePel(),  //table父节点
        _table = $$("table", { style: { cssText: "border-spacing: 0;border-collapse: collapse;width: 100%;position: relative;table-layout:fixed;"} }, _pel),
        _tbody = $$("tbody", {}, _table),
        _width = Math.max(Math.floor(_table.clientWidth / col), 50)
    ;
    // var _width = Math.max(Math.floor(_table.clientWidth / col), 50);
    //循环创建tr td
    for (i = 0; i < row; i++) {
        _tr = $$("tr", {}, _frag);  //创建tr
        for (j = 0; j < col; j++) {
            _td = $$("td", { style: { width: _width + "px" }, "innerHTML": "<br />" }, _tr);
        }
    }
    _tbody.appendChild(_frag);    //修改
    U.UF.E.table.load(_table);
};

/**
* 换行并返回该行的div 然后在该行下面创建空div(防止表格后无法聚焦)
* return 创建表格的div(父节点)
*/
U.UF.E.table.createTablePel = function () {
    var _table = U.UF.E.table;
    //console.log(_table._range);
    var _range = U.UF.E.table._range,   //获取光标
        _div = U.UF.E.getLineElement(_range.startContainer);    //获取光标所在行的div
    if (_div.textContent !== "") {   //如果该行有内容 则新建一行div
        var _div = U.selectEl("#" + U.UF.E.key.addLine(_range).addLine)[0];
    }
    //   U.selectEl(_div).attr("contenteditable", "false");    //无内容的div(表格的父节点) 取消编辑效果
    _div.style.cssText = "overflow-y:hidden;padding-bottom:5px;padding-right:7px;width:90%";   //_div的样式
    U.UF.E.key.addLine(_range);   //在表格的父节点下添加div 防止无法聚焦
    _table.placeCaretAtEnd(_div);
    return _div;
};

/**
* 将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
* tableEl 表格元素
*/
U.UF.E.table.firstLinePeak = function (tableEl) {
    U.selectEl(tableEl).find(".U_UF_E_Table_peak").css("height", 0);  //原来有列尺的元素高度清0
    U.selectEl(tableEl).find(".U_UF_E_Table_peak").removeClass("U_UF_E_Table_peak");  //改变 删除所有列尺的zIndex为1的样式
    var _height = tableEl.clientHeight;  //获取表格的高
    var _colRuleList = tableEl.querySelectorAll("tr")[0].querySelectorAll(".U_MD_O_W_Table_colRule"); //获取第一行的列尺
    for (var i = 0, len = _colRuleList.length; i < len; i++) {
        var _colRule = _colRuleList[i];
        _colRule.style.height = _height + "px"; //所有列尺的高等于表格的高
        U.selectEl(_colRule).addClass("U_UF_E_Table_peak");
    }
};

/**
*
* @param table 防止选中事件时选中到表格外的元素而报错
*/
U.UF.E.table.tableOver = function (table) {
    U.selectEl(table).bind('mouseover', function () {    //判断鼠标是否在该table里 如果在 才可以选择区域
        this.over = true;
    });
    U.selectEl(table).bind('mouseout', function () {
        this.over = false;
    });
};

/**
*
* @param colrule 列尺(div) 添加左右拉伸事件
*/
U.UF.E.table.colExpanding = function (colrule) {
    var _div = colrule;
    U.selectEl(_div).bind({
        'mousedown': function (e) {
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
            this.style.backgroundColor = "#8cb3e0"; //修改列尺(div)的颜色
            var _table = U.UF.E.table;
            var _this = this;
            var _tdEl = this.parentNode;  //获取td(每个列对应一个td父节点)
            var _tableEl = _table.parentSelect(this, "table");    //获取所在的table
            var _tableElWidth = _tableEl.clientWidth;       //table当前的宽度
            var _trList = _tableEl.querySelectorAll("tr");    //获取所有的tr
            var _tdElIndex = _table.index(_tdEl);  //获取td在tr的索引位置(列)
            var _dis,   //移动的距离
                _disX;   //移动后的位置
            var _oMouseX = e.pageX;                                   //获取鼠标按下时的X坐标
            var _oX = parseInt(this.style.right);               //获取当前Left坐标
            var expandingMove = function (e) {                      //拖拽时移动用的函数
                U.UF.EV.stopDefault(e);                               //取消默认拖拽
                var _mouseX = e.pageX;                                //鼠标移动时的x坐标
                _dis = _mouseX - _oMouseX;                            //移动的距离
                _disX = _dis + _oX;                                   //移动后的位置
                U.selectEl(_this).css("right", -_disX + "px");             //同步当前的left
            };
            var expandingUp = function () {                  //拖拽时松开用的函数
                _this.style.backgroundColor = "";   //列尺颜色 变为空
                var _child;
                for (var i = 0, len = _trList.length; i < len; i++) {
                    var _colTdEl = U.selectEl("td", _trList[i])[_tdElIndex];   //列的td _trList[i].querySelectorAll("td")
                    _colTdEl.style.width = _colTdEl.offsetWidth + _disX + "px";    //同步宽度
                    var _colRule = _colTdEl.querySelectorAll('.U_MD_O_W_Table_colRule');    //该td对应的列尺
                    U.selectEl(_colRule).css("right", "0px"); //同步当前的left
                    _child = U.selectEl("div", _trList[i]);
                    _child[_child.length - 1].style.marginTop = _trList[i].offsetHeight + "px";
                }
                U.selectEl(document).unbind('mousemove', expandingMove);
                U.selectEl(document).unbind('mouseup', expandingUp);
            };
            U.selectEl(document).bind('mousemove', expandingMove);
            U.selectEl(document).bind('mouseup', expandingUp)
        },
        'dblclick': function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        },   //阻止td的双击
        'mousemove': function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
            U.UF.EV.stopDefault(e);                                //取消默认拖拽
        }
    });
};

/**
*
* @param rowrule 行尺(div) 添加上下拉伸事件
*/
U.UF.E.table.rowExpanding = function (rowrule) {   //高度扩张
    var _div = rowrule;
    U.selectEl(_div).bind({
        'mousedown': function (e) {
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
            this.style.backgroundColor = "#8cb3e0";
            U.UF.EV.stopBubble(e);                                     //阻止冒泡
            var _oMouseY = e.pageY;                                    //获取鼠标按下时的Y坐标
            var _this = this;
            var _oY = parseInt(this.style.marginTop);                 //获取当前Top坐标
            var _trEl = this.parentNode;                                //获取tr
            var expandingMove = function (e) {                           //拖拽时移动用的函数
                U.UF.EV.stopDefault(e);                                //取消默认拖拽
                var _mouseY = e.pageY;                                 //鼠标移动时的Y坐标
                var _dis = _mouseY - _oMouseY + _oY;                   //移动的距离
                _dis = Math.max(30, _dis);                              //拉伸后的tr的高度不能小于30px
                _trEl.style.height = _dis + "px";
                var clienHeight = _trEl.clientHeight; //tr的高度 会根据内容有个最小值 因此 这个tr最后的高度 才是最终值
                _dis = Math.max(clienHeight, _dis);
                _trEl.style.height = _dis + "px";
                U.selectEl(_this).css("margin-top", _dis + "px");
            };
            var expandingUp = function () {                  //拖拽时松开用的函数
                var _table = U.UF.E.table;  //简写命名空间    
                var _tableEl = _table.parentSelect(_this, "table");  //获取table元素
                _table.firstLinePeak(_tableEl); //更新第一行的列尺高度
                _this.style.backgroundColor = "";
                U.selectEl(document).unbind('mousemove', expandingMove);
                U.selectEl(document).unbind('mouseup', expandingUp);
            };

            U.selectEl(document).bind('mousemove', expandingMove);
            U.selectEl(document).bind('mouseup', expandingUp)
        },
        'mousemove': function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
            U.UF.EV.stopDefault(e);                                //取消默认拖拽
        }
    });
};


/*
* 添加文本框 并给文本框添加事件
* parent td元素(文本框父元素)
* text 为文本 可要可不要
*/
U.UF.E.table.createTextArea = function (parent, text) {
    var _textArea = $$("textarea", { className: "U_UF_E_Table_tdText", value: text || "", contenteditable: "true", inline: true }, parent);   //添加textarea 并且将td的内容放入textarea
    U.selectEl(_textArea).bind('mousedown', function (e) {
        U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素              //阻止冒泡
    }); //阻止td的冒泡 (选中效果 和 聚焦效果)
    var autoHeight = function (el) {  //表格自动适应高
        el.nodeType === 1 ? "" : el = el.target;    //el只能为textarea
        el.scrollHeight ? el.style.height = el.scrollHeight + "px" : "";   //此处为textarea的高度跟随文字输入的内容自动增高
        var _rowRuleList = U.selectEl(".U_MD_O_W_Table_rowRule");   //获取所有行尺
        for (var i = 0, len = _rowRuleList.length; i < len; i++) {
            var _trPel = _rowRuleList[i].parentNode;    //每个行尺 对应一个 tr元素
            _trPel.style.height = _trPel.clientHeight;  //使每个tr的height 等于 clientHeight
            U.selectEl(_rowRuleList[i]).css("margin-top", _trPel.clientHeight + "px");    //同步margintop 的位置
        }
    };
    autoHeight(_textArea);  //由于textarea输入自后td的高度会变化 因此所有行尺的位置重新定位
    U.selectEl(_textArea).bind('keydown', autoHeight);    //键盘监听 自动适应高
    U.selectEl(_textArea).bind('keyup', autoHeight);  //键盘监听 自动适应高
    U.selectEl(_textArea).bind('blur', function () {
        var _textla = U.selectEl(".U_UF_E_Table_tdText");
        var _tdEl = U.selectEl(".U_UF_E_Table_tdText")[0].parentNode;
        _tdEl.innerText = _textla[0].value;
        _textla.remove();
    });
}

/**
*
* @param td 添加鼠标拖拽效果的 td
* 给td添加鼠标拖拽的选中效果
*/
U.UF.E.table.dragCheckd = function (td) {
    var _tdEl = td;
    U.selectEl(_tdEl).bind('mousedown', function (e) {
        U.UF.EV.stopBubble(e); //阻止冒泡
        U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove(); //删除右键元素
        if (e.button != 2) {
            var _table = U.UF.E.table;
            //移除原本选中的效果
            U.selectEl(".U_UF_E_Table_tdCheckd").removeClass("U_UF_E_Table_tdCheckd");
            U.selectEl(".U_UF_E_Table_tdCurrent").removeClass("U_UF_E_Table_tdCurrent");
            //给td添加聚焦样式
            U.selectEl(this).addClass("U_UF_E_Table_tdCurrent");

            var _start = this; //获取点击元素
            var _startX = _table.index(_start); //记录x坐标轴
            var _startY = _table.index(this.parentNode);   //获取y坐标轴
            var _checkFlag = true;   //注意下面的_table.over是一个属性 防止选中区域在表格外面
            var _tableEl = _table.parentSelect(this, "table");    //获取父节点table

            //拖拽时移动用的函数
            var _drapMove = function (e) {
                var tagEl = e.path.filter(_filter)[0];
                if (tagEl) {
                    U.UF.EV.stopBubble(e); //阻止冒泡
                    if (!(_tableEl.over) || (tagEl === _start && _checkFlag)) return;    //此处防止选中table外元素 与 鼠标必须选中两个td才会有选中效果
                    _checkFlag = false;  //如果不同 则选中过两个元素
                    var _endX = _table.index(tagEl);   //结束点的x坐标
                    var _endY = _table.index(tagEl.parentNode); //结束点的y坐标
                    U.selectEl(".U_UF_E_Table_tdCheckd").removeClass("U_UF_E_Table_tdCheckd");
                    _table.tdAddClass(tagEl.parentNode, _startX, _startY, _endX, _endY);   //给开始点和结束点组成的矩形 添加选中的class
                }
            };
            var _dragUp = function () { //拖拽时松开用的函数
                U.selectEl(document).unbind('mousemove', _drapMove);
                U.selectEl(document).unbind('mouseup', _dragUp);
                _checkFlag = true;
            };
            var _filter = function (el) {
                return el.nodeName && el.nodeName === "TD"
            }
            U.selectEl(document).bind('mousemove', _drapMove);
            U.selectEl(document).bind('mouseup', _dragUp);
        }
    });
};

/**
*  添加右键
*  tableEl 表格元素
*/
U.UF.E.table.rightClick = function (tableEl) {
    var _table = U.UF.E.table;
    var leftAddCol = {
        innerHTML: '左侧添加列',
        onclick: function () {
            _table.addColumn("left");
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
        },
        onmousedown: function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        }
    };
    var rightAddCol = {
        innerHTML: '右侧添加列',
        onclick: function () {
            _table.addColumn("right");
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
        },
        onmousedown: function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        }
    };
    var upAddLine = {
        innerHTML: '向上添加行',
        onclick: function () {
            _table.addTr("up");
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
        },
        onmousedown: function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        }
    };
    var downAddLine = {
        innerHTML: '向下添加行',
        onclick: function () {
            _table.addTr("down");
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
        },
        onmousedown: function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        }
    };
    var removeCol = {
        innerHTML: '删除列',
        onclick: function () {
            _table.removeColumn();
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
        },
        onmousedown: function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        }
    };
    var removeLine = {
        innerHTML: '删除行',
        onclick: function () {
            _table.removeTr();
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
        },
        onmousedown: function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        }
    };
    var mergeCells = {
        innerHTML: '合并单元格',
        onclick: function () {
            _table.mergeCells();
            U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
        },
        onmousedown: function (e) {
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        }
    };
    var _arr = [leftAddCol, rightAddCol, upAddLine, downAddLine, removeCol, removeLine, mergeCells];
    U.selectEl(tableEl).bind('contextmenu', function (e) {
        U.UF.EV.stopBubble(e);                                    //阻止冒泡
        U.UF.EV.stopDefault();
        U.UF.EL.rightMenu(_arr, tableEl);
        U.selectEl("#U_UF_EL_rightmenu").bind('contextmenu', function (e) {   //右键元素属于table 因此需要阻止冒泡
            U.UF.EV.stopBubble(e);                                    //阻止冒泡
        });
    });
    U.selectEl(tableEl).bind('mousedown', function (e) {
        U.selectEl("#U_UF_EL_rightmenu")[0] && U.selectEl("#U_UF_EL_rightmenu")[0].remove();    //删除右键元素
    });
};

/**
*
* @param direction 参数为 "left" 或 "right"
* 左右侧添加列
*/
U.UF.E.table.addColumn = function (direction) {
    var _table = U.UF.E.table;
    var tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
    if (!tdList[0]) { //如果没有 选中的td
        if ($(".U_UF_E_Table_tdCurrent")[0]) { //再判断 有无聚焦的 td
            tdList = U.selectEl(".U_UF_E_Table_tdCurrent");
        } else {
            return; //如果没有 则直接返回
        }
    }
    var _tdEl;
    if (direction === "left") {
        _tdEl = tdList[0];
    } else if (direction === "right") {
        _tdEl = tdList[tdList.length - 1];
    }
    _table.insertTd(_tdEl, direction);
};

/**
*
* @param td  td元素
* @param direction  供添加左右列用的api 参数为 "left" 或 "right"
* 向每个tr的列(td) 前方或后方插入td
*/
U.UF.E.table.insertTd = function (td, direction) {
    var _table = U.UF.E.table;
    var _tdEl = td,
            _index = _table.index(_tdEl),    //在tr中位于所有td的位置
            _dir = direction;
    var _tableEl = _table.parentSelect(_tdEl, 'table');
    var _trList = U.selectEl(_tableEl).find("tr");
    var _tableElWidth = _tableEl.offsetWidth; //记住当前的宽度

    for (var i = 0, len = _trList.length; i < len; i++) {  //遍历每个tr的列(td) 在前方或后方插入td
        var _currentColumn = U.selectEl(_trList[i]).find("td")[_index];    //当前列
        var _tdElClone = _tdEl.cloneNode(); //克隆td
        if (_dir === "left") {
            _table.Before(_currentColumn, _tdElClone);    //在列的前面添加td
        }
        else if (_dir === "right") {
            _table.After(_currentColumn, _tdElClone); //在列的后面添加td
        }
        var _colRule = $$("div", { style: { position: "absolute", top: 0, left: "-7px", "margin-left": _tdElClone.style.width, cursor: "col-resize", width: "7px" }, className: "U_MD_O_W_Table_colRule", inline: true }, _tdElClone); //列尺
        _table.colExpanding(_colRule); //添加左右拉伸事件
        _table.createTextArea(_tdElClone); //添加文本框
        _table.dragCheckd(_tdElClone);    //td拖拽的选中事件
        U.selectEl(_tdElClone).removeClass("U_UF_E_Table_tdCheckd"); //清楚添加后的列的选中的样式
        U.selectEl(_tdElClone).removeClass("U_UF_E_Table_tdCurrent");
    }
    _tableEl.style.width = _tableElWidth + _tdEl.offsetWidth + "px";
    _table.firstLinePeak(_tableEl);    //第一行tr的所有列尺添加zIndex为1
};

/**
*
* @param direction 参数为 "up" 或 "down"
* 上下添加行
*/
U.UF.E.table.addTr = function (direction) {
    var _table = U.UF.E.table;
    var tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
    if (!tdList[0]) { //如果没有 选中的td
        if ($(".U_UF_E_Table_tdCurrent")[0]) { //再判断 有无聚焦的 td
            tdList = U.selectEl(".U_UF_E_Table_tdCurrent");
        } else {
            return; //如果没有 则直接返回
        }
    }
    var _trEl, _trElClone;
    if (direction === "up") {
        _trEl = tdList[0].parentNode;
        _trElClone = _table.cloneTr(_trEl); //克隆tr 并给td 添加表格事件
        _table.Before(_trEl, _trElClone);
    } else if (direction === "down") {
        _trEl = tdList[tdList.length - 1].parentNode;    //向下插入行
        _trElClone = _table.cloneTr(_trEl); //克隆tr 并给td 添加表格事件
        _table.After(_trEl, _trElClone);
    }
    var _tableEl = _table.parentSelect(tdList[0], 'table');
    _table.firstLinePeak(_tableEl);    //将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
};

/**
*  删除行
*/
U.UF.E.table.removeTr = function () {
    var _table = U.UF.E.table;
    var tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
    if (!tdList[0]) { //如果没有 选中的td
        if ($(".U_UF_E_Table_tdCurrent")[0]) { //再判断 有无聚焦的 td
            tdList = U.selectEl(".U_UF_E_Table_tdCurrent");
        } else {
            return; //如果没有 则直接返回
        }
    }
    var start = _table.index(tdList[0].parentNode);
    var end = _table.index(tdList[tdList.length - 1].parentNode);
    var _tableEl = _table.parentSelect(tdList[0], "table");
    var _parentDiv = _table.parentSelect(_tableEl, "div");
    var _trList = U.selectEl(_tableEl).find("tr");
    for (var i = start; i <= end; i++) {
        _trList[i].remove();
    }
    if (!(_tableEl.querySelectorAll("tr").length)) {
        _parentDiv.remove();
        return
    }
    _table.firstLinePeak(_tableEl);    //将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
};

/**
*
* @param tr 需要克隆的tr
* 克隆tr 并添加表格事件
*/
U.UF.E.table.cloneTr = function (tr) {
    var _table = U.UF.E.table;
    var _trNodes = tr.cloneNode(true); //带子节点的tr
    var _trClone = tr.cloneNode();  //无子节点的tr
    var _cloneTd = U.selectEl(_trNodes).find("td");
    for (var i = 0, len = _cloneTd.length; i < len; i++) {
        var _td = _cloneTd[i].cloneNode();
        U.selectEl(_td).rmAttr("rowspan");   //删除跨行的属性
        _trClone.appendChild(_td);
        var _colRule = $$("div", { style: { position: "absolute", top: 0, left: "-7px", "margin-left": _td.style.width, cursor: "col-resize", width: "7px" }, className: "U_MD_O_W_Table_colRule", inline: true }, _td); //列尺
        _table.colExpanding(_colRule); //添加左右拉伸事件
        //_table.tdDbClick(_td); //添加双击事件
        _table.createTextArea(_td);
        _table.dragCheckd(_td);    //td拖拽的选中事件
    }
    var _rowRule = $$("div", { style: { position: "absolute", zIndex: "1", left: 0, "margin-top": "30px", cursor: "row-resize", height: "3px", width: "100%" }, className: "U_MD_O_W_Table_rowRule", inline: true }, _trClone); //行尺
    _table.rowExpanding(_rowRule);  //上下拉伸事件
    U.selectEl(_trClone).find(".U_UF_E_Table_tdCheckd").removeClass("U_UF_E_Table_tdCheckd");    //删除所有选中表格和 聚焦表格的样式
    U.selectEl(_trClone).find(".U_UF_E_Table_tdCurrent").removeClass("U_UF_E_Table_tdCurrent");
    return _trClone;
};

/**
*  合并单元格功能
*/
U.UF.E.table.mergeCells = function () {
    var _table = U.UF.E.table;
    var _tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
    if (_tdList.length <= 1) return;
    var _x1 = _table.index(_tdList[0]);  //x坐标开始点
    var _y1 = _table.index(_tdList[0].parentNode); //y坐标开始点
    var _x2 = _table.index(_tdList[_tdList.length - 1]); //x坐标结束点
    var _y2 = _table.index(_tdList[_tdList.length - 1].parentNode);  //y坐标结束点
    var _tableEl = _table.parentSelect(_tdList[0], "table");    //获取table元素
    var _trList = _tableEl.querySelectorAll("tr");  //获取table里所有tr
    var _text = "";     //合并后的总内容
    var allWidth = 0;   //合并后的总宽度
    for (var i = _y1; i <= _y2; i++) {  /*该循环*/
        var _trAllTd = _trList[i].querySelectorAll("td"); //获取选中表格的所在tr
        for (var j = _x1; j <= _x2; j++) { // 获取选中表格的 所在td
            var _tdEl = _trAllTd[j];    //获取每个选中的单元格
            _text += _tdEl.innerText;   //合并内容
            if (i === _y1) { //只计算选中表格第一行 的总宽度
                allWidth += _tdEl.offsetWidth;
            }
            if (i === _y1 && j === _x1) continue;    //第一个td就跳过 其他的则display为 none
            U.selectEl(_tdEl).css("display", "none");
        }
    }

    var _textNode = document.createTextNode(_text); //文字节点 _text为总内容
    var _firstNode = _table.getFirstText(_tdList[0]);   //获取被合并单元格的td所在的文字节点
    _firstNode ? _firstNode.remove() : ""; //如果存在文字节点 则删除
    _tdList[0].appendChild(_textNode); //然后将新创建的总文字节点 添加到该单元格里
    _tdList[0].style.width = allWidth + "px"; //添加总宽度
    var _col = U.selectEl(_tdList[0]).attr("colspan");
    _col <= _x2 - _x1 + 1 ? U.selectEl(_tdList[0]).attr("colspan", _x2 - _x1 + 1) : ""; //跨的列数
    U.selectEl(_tdList[0]).attr("rowspan", _y2 - _y1 + 1); //跨的行数
    U.selectEl(_tdList[0].querySelector(".U_MD_O_W_Table_colRule")).css("margin-left", allWidth + 'px');   //更新 列尺的位置
    _table.firstLinePeak(_tableEl);    //将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
};

/**
* 删除列
*/
U.UF.E.table.removeColumn = function () {
    var _table = U.UF.E.table
    var tdList = U.selectEl(".U_UF_E_Table_tdCheckd");
    if (!tdList[0]) { //如果没有 选中的td
        if ($(".U_UF_E_Table_tdCurrent")[0]) { //再判断 有无聚焦的 td
            tdList = U.selectEl(".U_UF_E_Table_tdCurrent");
        } else {
            return; //如果没有 则直接返回
        }
    }
    var _start = _table.index(tdList[0]);  //列的开始位置
    var _end = _table.index(tdList[tdList.length - 1]); //列的结束位置

    var _tableEl = _table.parentSelect(tdList[0], 'table');
    var _trList = U.selectEl(_tableEl).find("tr");
    var _widthSum = 0;  //删除列的总宽
    for (var i = 0, len = _trList.length; i < len; i++) {
        var _tdList = U.selectEl(_trList[i]).find("td");
        for (var j = _start; j <= _end; j++) {
            i === 0 ? _widthSum += _tdList[j].offsetWidth : "";    //只计算第一行删除的列宽
            _tdList[j].remove();
        }
    }
    _tableEl.style.width = _tableEl.offsetWidth - _widthSum + "px";
    var _tdLen = _tableEl.querySelectorAll("td").length;  //获取当前列的长度
    if (!_tdLen) {    //如果table不存在td 则删除table和 table父节点(div)
        var _parentDiv = _table.parentSelect(_tableEl, "div");
        _parentDiv.remove();
        return
    }
    _table.firstLinePeak(_tableEl);    //将表格的第一个tr里的所有列尺元素 添加 zindex为1 的样式
};

/**
* 添加点击时的聚焦效果 并且若存在textarea元素 则删除并获取textarea的值给td
*/
U.UF.E.table.removeFocus = function () {        //添加点击时的聚焦效果 并且若存在textarea元素 则删除并获取textarea的值给td
    U.selectEl(".U_UF_E_Table_tdCheckd").removeClass("U_UF_E_Table_tdCheckd");
    U.selectEl(".U_UF_E_Table_tdCurrent").removeClass("U_UF_E_Table_tdCurrent");
    return;
    var _textArea = U.selectEl(".U_UF_E_Table_tdText")[0],        //如果存在textarea元素 则将其变为文本
            _pel;
    _textArea ? _pel = _textArea.parentNode : ""; //如果textArea存在 先获取父节点td 然后将其变为文本
    if (_pel) {
        var _textNode = document.createTextNode(_textArea.value);
        _pel.appendChild(_textNode);
        _textArea.remove();
    }
    var _rowRuleList = U.selectEl(".U_MD_O_W_Table_rowRule"); //使div的margintop 及时更新
    for (var i = 0, len = _rowRuleList.length; i < len; i++) {
        var _trEl = _rowRuleList[i].parentNode;
        _trEl.style.height = _trEl.clientHeight;
        U.selectEl(_rowRuleList[i]).css("margin-top", _trEl.clientHeight + "px");
    }
};

/**
*
* @param tr 获取所有tr用的(遍历所有tr)
* @param x1 开始点x坐标
* @param y1 开始点y坐标
* @param x2 结束点x坐标
* @param y2 结束点y坐标
*/
U.UF.E.table.tdAddClass = function (tr, x1, y1, x2, y2) {   //获取首尾坐标轴 最后组成矩形 然后添加选中的class
    var _trList = tr.parentNode.querySelectorAll("tr");
    var _x1 = Math.min(x1, x2);
    var _x2 = Math.max(x1, x2);
    var _y1 = Math.min(y1, y2);
    var _y2 = Math.max(y1, y2);
    for (var i = _y1; i <= _y2; i++) {
        var _tdList = _trList[i].querySelectorAll("td");
        for (var j = _x1; j <= _x2; j++) {
            U.selectEl(_tdList[j]).addClass("U_UF_E_Table_tdCheckd");
        }
    }
}

/**
*
* @param el 元素
* @returns {number} 返回当前元素在所有同类型元素 的第几个位置
*/
U.UF.E.table.index = function (el) {
    var _el = el;
    var _name = _el.nodeName;   //获取该元素的节点名
    var _list = _el.parentNode.querySelectorAll(_name); //获取父节下的所有自己的节点
    for (var i = 0, len = _list.length; i < len; i++) {
        if (_list[i] === _el) {
            return i;   //返回在数组的索引
        }
    }
};
/**
* 获取td的第一个文本元素
*/
U.UF.E.table.getFirstText = function (td) {
    var _child = td.childNodes;
    for (var i = 0, len = _child.length; i < len; i++) {
        if (_child[i].nodeType === 3) {
            return _child[i];
        }
    }
    return false;
}
/*获取指定标签的父节点*/
U.UF.E.table.parentSelect = function (el, type) {
    var _this = el;
    var type = type.toUpperCase();
    if (_this.tagName === type) return _this;
    var parent = _this.parentNode;
    while (parent.tagName !== type) {
        parent = parent.parentNode;
    }
    return parent;
};
/*在元素前面插入新元素*/
U.UF.E.table.Before = function (el, newEl) {
    var _this = el;
    var parentEl = _this.parentNode;
    parentEl.insertBefore(newEl, _this);
};
/*在元素后面插入新元素*/
U.UF.E.table.After = function (el, newEl) {
    var _this = el;
    if (_this && _this.parentNode) {
        var parentEl = _this.parentNode;
        var child = parentEl.childNodes;
        var last = child[child.length - 1] || parentEl.lastChild;
        if (last === _this) {
            parentEl.appendChild(newEl);
        } else {
            parentEl.insertBefore(newEl, _this.nextSibling);
        }
        return newEl;
    }
};

/**
*  使光标聚焦在该元素后面
* @param el 需要文字聚焦的 元素节点
*/
U.UF.E.table.placeCaretAtEnd = function (el) {    //传入光标要去的节点对象
    if (el.collapse) {   //如果存在el.collapsed 则是range
        var range = el;
        range.collapse(false);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
        return;
    }
    if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
        el.focus && el.focus();
        var range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (typeof document.body.createTextRange != "undefined") {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
    }
};

/*
合并单元格使用bug:
1.选中表格时 如出现行和列对不齐时 除了删除列不会有问题以外 其他都会出问题	
解决思路:由于合并单元格后 每行的td都对不齐了 因此需要修改选中td的接口 不准出现参差不齐的情况

2.在合并单元格的那一列用添加列 删除列会有bug   
解决思路: 由于合并单元格时 有占用两列或两行的情况 因此需要在添加列删除列那里将占用两列以上的情况考虑进去 针对colspan属性做判断

3.在合并单元格的那一行除了 向上添加行功能 其他都会有bug
解决思路:由于跨行合并单元格 会使第第一行变成占2行或以上 其他行display为none 因此如果向下添加行则需要将display为none 消掉 主要也是需要针对rowspan属性做判断
*/
;
///<jscompress sourcefile="Outside.js" />
Namespace.register("U.UF.OT"); //第三方接口


/**
* 生成微信二维码
*
* @bindel  {element} 绑定点击的元素 必填 
* @href  {string} 分享的地址 选填 默认值:当前游览器网页地址
* return {element} 返回创建好得元素
*/
U.UF.OT.weChatShareCode = function codeLayout(bindel, href, parent) {
    if (typeof bindel != 'object')  //判断bindel是否是元素
        return false;

    parent = parent ? parent : document.body; //parente默认为document.body
    var _codeBox;
    if (!$('#wxfrom', parent)[0]) {//   判断二维码是否存在
        _codeBox = $$('div', { id: "wxfrom", style: { cssText: 'display: none; position:fixed; top:0; left:0; bottom:0; right:0; margin:auto; width:251px; height:332px; padding:10px; background-color: #f4f4f4; border: 1px solid #b9b9b9;'} }, parent || document.body);
        $$('span', { innerText: "分享到微信朋友圈", style: { cssText: 'font-weight: bold'} }, _codeBox);
        $$('span', { innerText: 'x', style: { cssText: 'margin-left:140px; font-size: 18px; font-weight: bold; cursor:pointer' }, onclick: function () {
            _codeBox.style.display = 'none';
        }
        }, _codeBox);
        var _codeShowArea = $$('div', { style: { cssText: "padding:20px 10px;"} }, _codeBox);
        // U.UF.QR.generate("230", "235", "black", "#f4f4f4", href || window.location.href, _codeShowArea);
        $$('div', { innerHTML: "打开微信,点击底部的“发现”,<br/>使用“扫一扫”即可将网页分享至朋友圈。" }, _codeBox);
    } else {
        _codeBox = U.selectEl('#wxfrom', parent)[0];
    }
    U.selectEl(bindel).bind({
        click: function () {
            U.UF.QR.generate("230", "235", "black", "#f4f4f4", href || window.location.href, _codeShowArea);
            _codeBox.style.display = '';
        }
    })

    return _codeBox;
}

/**
* qq好友分享
*
* @url  {string} 分享的网页地址
* @title  {string} 标题
* @pic  {string} 图片绝对路径
* @desc  {string} 分享介绍
* @summary  {string} 分享内容
*/
U.UF.OT.qqFriendShare = function (url, title, pic, desc, summary) {
    var _sharesinastring = 'https://connect.qq.com/widget/shareqq/index.html?url=' + encodeURIComponent(url || window.location.href)
    + '&title=' + encodeURIComponent(title || '这文件超棒的,分享给你看看!')
    + '&pic=' + pic || ""
    + '&desc=' + desc || ""
    + '&summary=' + summary || "";
    window.open(_sharesinastring, 'newwindow', 'height=600,width=864,top=300,left=300');
}

/**
* 新浪微博分享
*
* @url  {string} 分享的网页地址
* @title  {string} 标题
* @pic  {string} 图片绝对路径
*/
U.UF.OT.weiboShare = function (url, title, pic) {
    var _sharesinastring = 'http://v.t.sina.com.cn/share/share.php?url=' + encodeURIComponent(url || window.location.href)
    + '&title=' + encodeURIComponent(title || '这文件超棒的,分享给你看看!') + '&content=utf-8'
    + '&pic=' + pic || "";
    window.open(_sharesinastring, 'newwindow', 'height=500,width=800,top=300,left=300');
}
;