/**
 * cmp核,cmp的全部框架和提供的一些框架内实用的工具类,包括<br>
 *     <ul>
 *         <li>语言环境判断</li>
 *         <li>运行环境判断</li>
 *         <li>网络环境判断</li>
 *         <li>设备型号</li>
 *         <li>ajax</li>
 *         <li>页面跳转历史堆栈</li>
 *         <li>html模板引擎</li>
 *         <li>手机端事件处理等</li>
 *         <li>常用的js原生对象进行扩展</li>
 *     </ul>
 *
 * @module Core
 * @subtitle cmp核心模块
 */

/**
 * html模板引擎<br>语法和jsp的模板是一致的,使用<%  (左尖括号+百分号)作为语法开始节点 ;使用%>  (百分号+右尖括号)作为语法节点结束;结束for,while,if,else逻辑
 * @namespace cmp
 * @class tpl
 * @constructor
 * @param {String} str;模板html字符串
 * @param {Object} data:插入的数据
 * @example
 * ```
 * <script>
 *     cmp.tpl("<span><%=this.id %></span><div><% if(d){ %><span>hah</span><% }else{ %> sahhdas<% } %></div>",{id:"123456"})//模板和jsp的格式一致
 * </script>
 * ```
 * @cutline ![模板引擎](../../doc_cutline_img/tpl.png)
 * @returns {String} 返回有数据展示的组装后的Html字符串
 */

/**
 * 程序运行平台类<br>
 * @class platform
 */

/**
 * 获取当前登录语言环境,一般用于国际化
 * @namespace cmp
 * @class language
 * @constructor
 * @example
 * ```
 * <script>
 *     cmp.language   //"zh-CN"  / "zh-TW"  /"en"
 * </script>
 * ```
 * @returns {String} 语言环境<br>
 * <ul>
 *     <li>zh-CN:简体中文环境</li>
 *     <li>zh-TW:繁体中文环境</li>
 *     <li>en:英文环境</li>
 * </ul>
 */

/**
 * 获取移动端平台环境
 * @namespace cmp
 * @class os
 * @constructor
 * @returns {Boolean} 移动端平台环境<br>
 * <ul>
 *     <li>cmp.os.mobile:是否为移动终端</li>
 *     <li>cmp.os.ios:是否为ios终端</li>
 *     <li>cmp.os.android:android终端或uc浏览器</li>
 *     <li>cmp.os.iPhone:是否为iPhone或者QQHD浏览器</li>
 *     <li>cmp.os.iPad:是否iPad</li>
 * </ul>
 * @example
 * ```
 * <script>
 *     if(cmp.os.ios){
 *        //做ios的业务逻辑
 *     }else if(cmp.os.android){
 *       //做Android的业务逻辑
 *     }else if(cmp.os.iPhone){
 *        //做iphone手机的业务逻辑
 *     }else if(cmp.os.iPad){
 *        //做iPad的业务逻辑
 *     }
 * </script>
 * ```
 */

/**
 * 获取移动端平台版本号
 * @namespace cmp
 * @class version
 * @constructor
 * @returns {String} 移动端平台版本号<br>
 * @example
 * ```
 * <script>
 *     cmp.os.version
 * </script>
 * ```
 */

/**
 * 获取程序运行平台环境,避免开发者在开发时不考虑运行环境,导致一些功能在其平台上不能使用
 * @namespace cmp
 * @class platform
 * @constructor
 * @returns {Boolean} 移动端平台环境<br>
 * <ul>
 *     <li>cmp.platform.wechat:判断是否是微信的壳</li>
 *     <li>cmp.platform.CMPShell:判断是否是CMP的壳</li>
 *     <li>cmp.platform.DDShell:判断是否是钉钉的壳</li>
 *     <li>cmp.platform.wxwork:判断是否是企业微信的壳</li>
 *     <li>cmp.platform.wechatOrDD:判断是否是微协同的环境</li>
 * </ul>
 * @example
 * ```
 * <script>
 *     if(cmp.platform.wechatOrDD){
 *          //做微协同的业务逻辑
 *     }else if(cmp.platform.CMPShell){
 *        //做M3的业务逻辑
 *     }
 * </script>
 * ```
 */

/**
 * 系统类
 * @class system
 */

/**
 * 判断是否支持附件上传下载,避免盲目做业务应用
 * @method filePermission
 * @namespace cmp
 * @constructor
 * @returns {Boolean} 是否有附件操作功能 true:有,false:没有
 *
 */

/**
 * 获取移动设备信息,<br>
 *     微协同不支持此API
 * @namespace cmp
 * @class info
 * @constructor
 * @returns {Object}CMPDevice 获取移动设备信息<br>
 * <ul>
 *     <li>CMPDevice.available:设备</li>
 *     <li>CMPDevice.platform:设备平台</li>
 *     <li>CMPDevice.version:设备版本</li>
 *     <li>CMPDevice.uuid:设备id</li>
 *     <li>CMPDevice.model:设备型号</li>
 *     <li>CMPDevice.manufacturer:设备生成厂家</li>
 *     <li>CMPDevice.enbrand:设备牌子(英文)</li>
 *     <li>CMPDevice.cnbrand:设备牌子(中文)</li>
 * </ul>
 * @example
 * ```
 * //注:微协同不支持此API调用
 * <script>
 *     var deviceInfo =  cmp.device.info();
 *     var available = deviceInfo.available;//true
 *     var platform = deviceInfo.platform;//"androidphone"
 *     var version = deviceInfo.version;//6.0.1
 *     var uuid = deviceInfo.uuid;//b4a3dddfd263c656
 *     var model = deviceInfo.model;//SM-A7100
 *     var manufacturer = deviceInfo.manufacturer;//samsung
 *     var enbrand = deviceInfo.enbrand;//samsung
 *     var cnbrand = deviceInfo.cnbrand;//三星
 * </script>
 * ```
 */

/**
 * 获取平台运行m3工程的ip地址,用于数据请求的ip拼接,如http://10.5.6.240:88
 * @namespace cmp
 * @class serverIp
 * @constructor
 * @returns {String} m3工程ip地址<br>
 *     兼容cmp和微信端
 * @example
 * ```
 * //注:M3接入第三方页面,如果是跨域了,此参数不生效
 * <script>
 *     cmp.serverIp//该值为常量,如http://10.5.6.240:88
 * </script>
 * ```
 */

/**
 * 获取平台运行m3工程,如http://10.5.6.240:88/seeyon
 * @namespace cmp
 * @class origin
 * @constructor
 * @returns {String} m3工程<br>
 *     兼容cmp和微信端
 * @example
 * ```
 * //注:M3接入第三方页面,如果是跨域了,此参数不生效
 * <script>
 *     cmp.origin//该值为常量,如http://10.5.6.240:88/seeyon
 * </script>
 * ```
 */
/**
 * 获取平台运行m3工程(seeyon工程),如http://10.5.6.240:88/seeyon
 * @namespace cmp
 * @class seeyonbasepath
 * @constructor
 * @returns {String} m3工程<br>
 *     兼容cmp和微信端
 * @example
 * ```
 * //注:M3接入第三方页面,如果是跨域了,此参数不生效
 * <script>
 *     cmp.seeyonbasepath//该值为常量 如http://10.5.6.240:88/seeyon
 * </script>
 * ```
 */

/**
 * 获取平台运行m3工程,当前登录人员token值(用于单点登录时来取这个值)
 * @namespace cmp
 * @class token
 * @constructor
 * @returns {String} 当前登录人员token值<br>
 *     适配微信端
 * @example
 * ```
 * //注:此常量只在微协同上有用
 * //注:如果是跨域页面,此参数不生效
 * <script>
 *     cmp.token//该值为常量 如hsdHS87-JDH18JSJ-KK
 * </script>
 * ```
 */

/**
 * 获取平台运行m3工程,当前登录人员信息
 * @namespace cmp
 * @class member
 * @constructor
 * @returns {Object} 当前登录人员信息<br>
 *     适配cmp壳,
 *     微协同只能获取人员名
 * @example
 * ```
 * //注:如果是跨越页面,此参数不生效
 * <script>
 *     cmp.member//该值为常量
 *     //=========M3 端========================//
 *     //其信息包括以下:
 *     cmp.member = {
 *         accName:"北京致远互联软件股份有限公司" ,  //单位名称
 *         accShortName:"致远互联",//单位简称
 *         accountId:"6777373",//单位id
 *         departmentId:"77838883",//人员部门id
 *         departmentName:"移动平台"//人员部门名称
 *         email:"883737@163.com",//人员email
 *         iconUrl:"https://m.seeyon./mobile_portal/seeyon/rest/orgMember/avatar/-55555?maxWidth=200&data=76",//人员头像
 *         id:"7372837",//人员id
 *         name:"姚明",//人员名称
 *         levelName:"普通员工",//人员职级名
 *         levelId:"555555",//人员职级id
 *         postName:"android开发工程师"//人员岗位名
 *         postId:"-2690007481908510274"//人员岗位id
 *         tel:"634663"//人员电话号码
 *     }
 *     //==========微协同端================//
 *     cmp.member = {
 *         name:"姚明"
 *     }
 * </script>
 * ```
 */

/**
 * 封装的部分移动端常用的事件:<br>
 * @class event
 */

/**
 * 监听页面的ready事件,兼容了cmp壳和微信、pc端<br>
 *     <span style="color:red">!cmp壳必须通过此ready才能入口</span>
 * @method ready
 * @namespace cmp.event
 * @param {Function} fn ready后的回调函数,即呈现的入口函数
 * @example
 * ```
 * <script>
 *     cmp.ready(function (){
 *         //开发者的业务应用写在这里
 *     });
 * </script>
 * ```
 */

/**
 * 主动触发事件
 * @method trigger
 * @namespace cmp.event
 * @param {String} type 主动触发的事件类型,比如click,tap等
 * @param {Object} dom 主动触发事件的dom对象
 * @param {Object|String|Array} data 主动触发时的需要传递的参数
 * @example
 * ```
 * <script>
 *     cmp.event.trigger("tap",dom1);
 *
 *     ****************************************************************
 *     document.addEvenetListener("UC_getMessage",function(event){
 *           var data = event.data;//从event对象中获取data
 *     });
 *
 *     cmp.event.trigger("UC_getMessage",document,data);//触发document监听的UC_getMessage事件
 * </script>
 * ```
 */

/**
 * cmp封装的点击事件,优化了在手机端,tap、click事件的延迟问题和点穿问题
 * @method click
 * @namespace cmp.event
 * @param {Object} dom 绑定事件的dom
 * @param {Function} fun 事件绑定的回调函数
 * @example
 * ```
 * <script>
 *     cmp.event.click(dom1,function(){
 *          //do something
 *     });
 * </script>
 * ```
 */

/**
 * 移动端长按事件 默认长按700毫秒就会促发事件
 * @method touchHold
 * @namespace cmp.event
 * @param {Object} dom 绑定事件的dom
 * @param {Function} fun 事件绑定的回调函数
 * @example
 * ```
 * <script>
 *     cmp.event.touchHold(dom1,function(){
 *          //do something
 *     });
 * </script>
 * ```
 */

/**
 * 页面缓存<br>
 *     封装了H5原生的localStorage和sessionStorage的增删改查
 * @class storage
 */

/**
 * 保存缓存数据
 * @method save
 * @namespace cmp
 * @param {String} key 保存的缓存的key名字
 * @param {String} value 保存的key对应的value值
 * @param {Boolean} scope 是否启用sessionStorage,true :启用,false,不启用,使用的是localStorage
 * @example
 * ```
 * <script>
 *     cmp.storage.save("name","cmp");
 * </script>
 * ```
 */

/**
 * 获取缓存数据
 * @method get
 * @namespace cmp
 * @param {String} key 获取的缓存的key名字
 * @param {Boolean} scope 是否启用sessionStorage,true :启用,false,不启用,使用的是localStorage
 * @example
 * ```
 * <script>
 *     var name =  cmp.storage.get("name");
 *     //name 就等于  "cmp"
 * </script>
 * ```
 * @return {String} 返回缓存的数据
 */

/**
 * 需要删除的缓存数据
 * @method delete
 * @namespace cmp
 * @param {String} key 获取的缓存的key名字
 * @param {Boolean} scope 是否启用sessionStorage,true :启用,false,不启用,使用的是localStorage
 * @example
 * ```
 * <script>
 *     cmp.storage.delete("name");
 * </script>
 * ```
 */

/**
 * 清空所有缓存数据
 * @method deleteAll
 * @namespace cmp
 * @param {Boolean} scope 是否启用sessionStorage,true :启用,false,不启用,使用的是localStorage
 * @example
 * ```
 * <script>
 *     cmp.storage.deleteAll();
 * </script>
 * ```
 */

/**
 * 获取所有缓存数据的个数
 * @method size
 * @namespace cmp
 * @param {Boolean} scope 是否启用sessionStorage,true :启用,false,不启用,使用的是localStorage
 * @example
 * ```
 * <script>
 *     var valueSize = cmp.storage.size();
 * </script>
 * ```
 * @return {Number} 返回个数
 */

/**
 * 将dom抽取成json数据,用于页面跳转前,将页面状态的数据进行记忆
 * @method dom2json
 * @namespace cmp
 * @param {Array} domains 需要被抽取成json数据的dom的id数组,该dom数组的id,应该包括,页面中的textarea,input,select有输入情况的控件
 * @example
 * ```
 * <script>
 *     cmp.storage.dom2json(["input1","input2","textarea1"]);
 * </script>
 * ```
 * @return {Object} 返回组装好的json对象
 */

/**
 * 将json数据回填进之前记忆的dom中
 * @method json2dom
 * @namespace cmp
 * @param {Object} json 将json对象,跳转之前记忆的数据
 * @example
 * ```
 * <script>
 *     cmp.storage.json2dom({});
 * </script>
 * ```
 */

/**
 * 数据库<br>
 *     封装了H5的数据库,用于保存大数据或持久化的数据保存
 *     H5的数据异步操作,增删改查都是异步执行的,需要定义callback回调函数
 * @class storageDB
 */

/**
 * 保存数据
 * @method save
 * @namespace cmp
 * @param {String} key 保存数据的key名字
 * @param {String} value 保存的key对应的value值
 * @param {Function} callback 回调函数
 * @example
 * ```
 * <script>
 *     cmp.storageDB.save("key","value",function(result){
 *            if(result.success){
 *                 //保存成功
 *            }else {
 *                //保存失败
 *                var errorCode = result.code;//错误码:91001打开数据失败;91002保存数据失败
 *                var errorMsg = result.error;//错误信息
 *            }
 *     });
 * </script>
 * ```
 */

/**
 * 获取数据
 * @method get
 * @namespace cmp
 * @param {String} key 获取数据的key值
 * @param {Function} callback 回调函数
 * @example
 * ```
 * <script>
 *     cmp.storageDB.get("key",function(result){
 *            if(result.success){
 *                 //获取数据成功
 *                 var data = result.data;//取出数据
 *            }else {
 *                //获取失败
 *                var errorCode = result.code;//错误码:91001打开数据失败;91003获取数据失败
 *                var errorMsg = result.error;//错误信息
 *            }
 *     });
 * </script>
 * ```
 */

/**
 * 根据某个key值删除数据
 * @method delete
 * @namespace cmp
 * @param {String} key 需要删除的key
 * @param {Function} callback 回调函数
 * @example
 * ```
 * <script>
 *     cmp.storageDB.delete("key",function(result){
 *            if(result.success){
 *                 //删除数据成功
 *            }else {
 *                //删除失败
 *                var errorCode = result.code;//错误码:91001打开数据失败;91004删除数据失败
 *                var errorMsg = result.error;//错误信息
 *            }
 *     });
 * </script>
 * ```
 */

/**
 * 清空数据库
 * @method deleteAll
 * @namespace cmp
 * @param {Function} callback 回调函数
 * @example
 * ```
 * <script>
 *     cmp.storageDB.deleteAll(function(result){
 *            if(result.success){
 *                 //清空数据库成功
 *            }else {
 *                //清空数据库失败
 *                var errorCode = result.code;//错误码:91001打开数据失败;91005清空数据失败
 *                var errorMsg = result.error;//错误信息
 *            }
 *     });
 * </script>
 * ```
 */

/**
 * ajax
 * <br>该ajax对部分服务器端返回的错误码进行处理(但是开发者也可以处理,错误码如下:
 *    <ul>
 *        <li>401:session失效</li>
 *        <li>1001:用户登陆超出并发数限制</li>
 *        <li>1002:用户登陆超出单位并发数限制</li>
 *        <li>1003:管理员踢人</li>
 *        <li>1004:另一个地方登录</li>
 *        <li>-1001:连接服务器失败</li>
 *        <li>-1005:断网了</li>
 *        <li>-1009:断网了</li>
 *    </ul>
 * @namespace cmp
 * @class ajax
 * @constructor
 * @param {Object} options 配置参数
 *      @param {String} options.type ajax请求类型,"GET"或者"POST",默认get
 *      @param {String/Object} [options.data] 请求参数,接受字符串,或者formData
 *      @param {String} options.url 请求地址
 *      @param {Object} [options.headers] 请求header
 *      @param {String} [options.dataType] 参数类型 默认json,接受formData
 *      @param {Number} [options.timeout] 请求超时设置,默认60000(单位:毫秒)
 *      @param {Boolean} [options.customCatchError] 设置是否自行捕获401,1001等那几个错误码,设置true,说明这几个错误开发者自行处理(默认false)
 *      @param {Function} [options.success] 请求成功回调
 *      @param {Function} [options.error] 请求失败回调
 *
 * @example
 * ```
 * <script>
 *     cmp.ajax({
 *        type:"POST",
 *        data:JSON.stringify(body),
 *        url:"http://xxxxx",
 *        headers:{
 *            'Content-Type': 'application/json; charset=utf-8',
 *            'Accept-Language' : "zh-CN",
 *            'option.n_a_s' : '1'
 *        },
 *        dataType:"json",
 *        success:function(result){
 *            //do something with success result;
 *        },
 *        error:function(error){
  *            if(!cmp.errorHandler(error)){ //先调用平台的错误统一处理机制
 *                //如果平台的统一处理机制处理不了,则自己写业务逻辑
 *                var code = error.code;
 *                if(code==500){
 *                   //根据code值做自己的业务逻辑
 *                }
 *            }
 *        }
 *     });
 *
 * </script>
 *
 * //常用的发送A8OA的rest接口可参考如下的方式:
 * //=============M3端=====================================//
 * <script>
 *     cmp.ajax({
 *        url:cmp.seeyonbasepath + '/rest/collaboration/getAll',//url的拼接  A8的域名 + rest + 应用模块名 + 具体接口名
 *        type:"POST",
 *        dataType:"json",
 *        data:JSON.stringify({"name":"x","sex":"nan"})
 *        headers:{
 *             'Content-Type': 'application/json; charset=utf-8',
 *            'Accept-Language' : "zh-CN",
 *            'option.n_a_s' : '1'
 *        },
 *        success:function(result){
 *        },
 *        error:function(error){
 *            if(!cmp.errorHandler(error)){ //先调用平台的错误统一处理机制
 *                //如果平台的统一处理机制处理不了,则自己写业务逻辑
 *                var code = error.code;
 *                if(code==500){
 *                   //根据code值做自己的业务逻辑
 *                }
 *            }
 *        }
 *     });
 *
 * //============微协同端=============================//
 *     cmp.ajax({
 *        url:cmp.seeyonbasepath + '/rest/collaboration/getAll',//url的拼接  A8的域名 + rest + 应用模块名 + 具体接口名
 *        type:"POST",
 *        dataType:"json",
 *        data:JSON.stringify({"name":"x","sex":"nan"})
 *        headers:{
 *             'Content-Type': 'application/json; charset=utf-8',
 *            'Accept-Language' : "zh-CN",
 *            'token':cmp.token,//微协同一定要带上此token
 *            'option.n_a_s' : '1'
 *        },
 *        success:function(result){
 *        },
 *        error:function(error){
 *            if(!cmp.errorHandler(error)){ //先调用平台的错误统一处理机制
 *                //如果平台的统一处理机制处理不了,则自己写业务逻辑
 *                var code = error.code;
 *                if(code==500){
 *                   //根据code值做自己的业务逻辑
 *                }
 *            }
 *        }
 *     });
 *     //注解:
 *     cmp.seeyonbasepath------------->rest接口的ip
 *     cmp.token------------------>微协同单点登录token值
 * </script>
 * ```
 */

/**
 * webview 操作(只支持在cmp壳里进行操作)
 * @class webview
 */

/**
 * 打开webview<br>
 *     <span style="color:red;">在一个应用中不能开启太多的webview,最多三个,这样会导致性能问题</span>
 * @method openWebView
 * @namespace cmp
 * @constructor
 * @param {Object} options 配置参数
 *      @param {String} options.url 需要webview装载的url地址
 *      @param {Boolean} [options.isNew] 是否是新开的一个webview,默认:true
 *      @param {String} options.header 原生导航栏标题
 *      @param {Boolean} [options.useNativebanner] 是否显示原生导航栏,默认:false,如果为true:android端原生导航栏会占一个高度为44px导航栏,ios端是64像素
 *      @param {Number} [options.iOSStatusBarStyle] ios状态栏颜色0=黑色 1=白色
 *      @param {Function} [options.success] 成功回调
 *      @param {Function} [options.error] 失败回调
 *
 * @example
 * ```
 * //注:微协同不支持此API
 * <script>
 *     cmp.openWebView({
 *         url: "",
 *           isNew: true,
 *           header: "header",
 *           useNativebanner:false, //是否显示原生导航栏
 *           "iOSStatusBarStyle":"", // ios状态栏颜色0=黑色 1=白色
 *           success: null,
 *           error: null
 *     });
 * </script>
 * ```
 */

/**
 * openWebView的扩展<br>
 *     只打开主webview,其他的子webview全部被关闭
 * @namespace cmp
 * @method openRootWebView
 * @constructor
 * @param {Object} options 配置参数
 *      @param {String} options.url 需要webview装载的url地址
 *      @param {Boolean} [options.isNew] 是否是新开的一个webview,默认:true
 *      @param {String} options.header 原生导航栏标题
 *      @param {Boolean} [options.useNativebanner] 是否显示原生导航栏,默认:false,如果为true:android端原生导航栏会占一个高度为44px导航栏,ios端是64像素
 *      @param {Number} [options.iOSStatusBarStyle] ios状态栏颜色0=黑色 1=白色
 *      @param {Function} [options.success] 成功回调
 *      @param {Function} [options.error] 失败回调
 *
 * @example
 * ```
 * //注:微协同不支持此API
 * <script>
 *     cmp.openRootWebView({
 *         url: "",
 *           isNew: true,
 *           header: "header",
 *           useNativebanner:false, //是否显示原生导航栏
 *           "iOSStatusBarStyle":"", // ios状态栏颜色0=黑色 1=白色
 *           success: null,
 *           error: null
 *     });
 * </script>
 * ```
 */

/**
 * 关闭当前webview
 * @namespace cmp
 * @method closeWebView
 * @constructor
 * @param {Object} options 配置参数
 *      @param {Function} [options.success] 成功回调
 *      @param {Function} [options.error] 失败回调
 *
 * @example
 * ```
 * //注:微协同不支持此API
 * <script>
 *     cmp.closeWebView({
 *           success: null,
 *           error: null
 *     });
 * </script>
 * ```
 */

/**
 * 判断当前程序运行的webview是否是主webview<br>
 * @namespace cmp
 * @method isRootWebView
 * @constructor
 * @param {Object} options 配置参数
 *      @param {Function} [options.success] 判断成功后的回调,会将判断值以{value:1}返回,如果value为1说明是主webview,如果为0则不是
 *      @param {Function} [options.error] 失败回调
 *
 * @example
 * ```
 * //注:微协同不支持此API
 * <script>
 *     cmp.isRootWebView({
 *           success: function(result){
 *               var value = result.value;
 *               if(value == 1){
 *                  //是主webview
 *               }else {
 *                 //不是主webview
 *               }
 *           },
 *           error: null
 *     });
 * </script>
 * ```
 */

/**
 * 页面转场<br>
 *     <ul>
 *         <li>为了避免在移动端,页面之间跳转在下一个页面还没有渲染出内容时,出现白屏的情况</li>
 *         <li>自定义跳转的动画切换,目前只提供从左向右和从右向左的动画,android是盖了一个进度圈</li>
 *         <li>当开始页面转场时,一个历史记录堆栈会被创建,并开始向这个堆栈存取删堆栈等操作</li>
 *         <li>该转场机制包含页面前进回退等一套,页面业务逻辑的堆栈,处理了模块与模块之间跳转页面历史记录堆栈混乱</li>
 *         <li>页面之间传参和取参</li>
 *     </ul>
 * @class href
 */

/**
 * 跳转到下一页<br>
 *     当跳转时,当前页面的url会进入历史记录堆栈中,如果是传有参数,该参数和当前url一起被记录进历史记录中
 * @namespace cmp.href
 * @method next
 * @constructor
 * @param {String} url 需要跳转的页面,如果需要打开新的webview需要重写cmp.href.openWebViewCatch()---返回值为1即开新的webview
 *      @param {String/Object} [params] 传递到下一个页面的参数
 *      @param {String/Object} [options] 跳转到下一页的动画效果,和可能是打开多webview后需要缓存的回调函数,
 *      <ul>
 *          <li>String:"left":从右向左(默认);"right":从左到右</li>
 *          <li>Object:{
 *               animated:true//是否开启动画(默认true),
 *               direction:"left"/"right" //动画方向
 *          }</li>
 *      </ul>
 *
 * @example
 * ```
 * <script>
 *     cmp.href.next("http://seeyon/m3/app/xxx.html",{data:"haha"},"left");
 *     或者
 *     打开webview时,
 *     cmp.href.openWebViewCatch = function(){return 1}//注:微协同不支持此API
 *
 *     cmp.href.next("http://newWebview"{value:"value"},{animated:true,direction:true})
 * </script>
 * ```
 */

/**
 * 返回上一页或返回上N页<br>
 *     当返回上一页时,组件会进行堆栈的删除,回退几个页面就删除几个堆栈<br>
 *     <span style="color:red;">特别说明一下,开发在next几个页面,回退时就最多回退next的几个,不然,组件如果判断出超出了堆栈,则默认回退到前一个页面,如果堆栈中都没有了,则会关闭当前的webview</span>
 * @namespace cmp.href
 * @method back
 * @constructor
 * @param {Number} [backIndex] 需要回退的页面数,默认不传,是回退上一页(注:请传正数)
 *      @param {String/Object} [queryParams] 回退页面时传递的参数,接受字符串和Object
 *      <ul>
 *          <li>String:如果是字符串,则等于queryParams即传给前面页面的search,如:"?backData=haha",该字符串会被拼接上回退的url地址上</li>
 *          <li>Object:{
 *               queryParams:"?backData=haha"
 *               data:{name:"haha"}//存入缓存的数据
 *          }</li>
 *      </ul>
 *
 * @example
 * ```
 * <script>
 *     cmp.href.back(5,{
 *         queryParams:"?backData=haha",
 *         data:{name:"haha"}
 *     });
 * </script>
 * ```
 */

/**
 * 跳转到指定页面<br>
 *     当调用此方式进行跳转,页面和参数不会进入历史记录的堆栈中
 * @namespace cmp.href
 * @method go
 * @constructor
 * @param {String} url 需要跳转的页面
 *      @param {String/Object} [params] 传递到下一个页面的参数
 *      @param {String/Object} [options] 跳转到下一页的动画效果,
 *      <ul>
 *          <li>String:"left":从右向左(默认);"right":从左到右</li>
 *          <li>Object:{
 *               animated:true//是否开启动画(默认true),
 *               direction:"left"/"right"  //动画方向
 *          }</li>
 *      </ul>
 *
 * @example
 * ```
 * <script>
 *     cmp.href.go("http://seeyon/m3/app/xxx.html",{data:"haha"},"left");
 * </script>
 * ```
 */

/**
 * 关闭页面,并清空历史记录堆栈<br>
 *     当调用此方法时,页面会被关闭,历史记录被清空,常常用于开发者认为再回退就应该关闭页面的情况<br>
 *      如果是cmp壳端,效果是关闭当前webview;微信端是退出微协同
 * @namespace cmp.href
 * @method closePage
 * @constructor
 * @example
 * ```
 * <script>
 *     cmp.href.closePage();
 * </script>
 * ```
 */

/**
 * 获取跳转传递参数<br>
 *     页面next或go到指定页面时,在该页面获取到跳转前传递的参数
 * @namespace cmp.href
 * @method getParam
 * @constructor
 * @param {String} [paramKey] 获取传递参数指定的key的值,默认:不传值,将存入的数据全部返回
 * @example
 * ```
 * <script>
 *     cmp.href.getParam();
 * </script>
 * ```
 * @return {String/Object} 返回传递数据,或传递数据的指定的key值
 */

/**
 * 获取back回退传递参数<br>
 *     页面back到指定页面时,在该页面获取到跳转前传递的参数
 * @namespace cmp.href
 * @method getBackParam
 * @constructor
 * @param {String} [paramKey] 获取传递参数指定的key的值,默认:不传值,将存入的数据全部返回
 * @example
 * ```
 * <script>
 *     cmp.href.getBackParam();
 * </script>
 * ```
 * @return {String/Object} 返回传递数据,或传递数据的指定的key值
 */

/**
 * 提供给开发者重写的方法,用于兼容调用next时是页面跳转还是打开一个新的webview<br>
 * @namespace cmp.href
 * @method openWebViewCatch
 * @constructor
 * @example
 * ```
 * //注:微协同不支持此API
 * <script>
 *     cmp.href.openWebViewCatch = function(){
 *          return 1;//next时打开webview
 *          return 2://next时不进行动画
 *     };
 * </script>
 * ```
 * @return {String/Object} 返回传递数据,或传递数据的指定的key值
 */





/**
 * 模拟的Map<br>
 * @class map
 */

/**
 * 通过调用此方法,构建一个新的Map对象,进行map的类似操作
 * @method build
 * @namespace cmp
 * @constructor
 * @example
 * ```
 * <script>
 *     var map = cmp.map.build() //生成一个map对象
 *        map.put("key","value");//向该map对象存入数据
 *        var value =  map.get("key");//获取对应key的值
 *        map.remove("key") //删除map中的key
 *        map.clear() //清空map
 *        var keys = map.keys() //获取map中所有的key,以数组的方式返回
 *        var values = map.values()//获取map中所有的value,以数组的方式返回
 *        map.containsKey("key") //判断map中是否包含某个key值
 *        map.containsValue("value") //判断map中是否包含某个value值
 *        var length = map.size() //获取map存入数据的个数
 *        map.isEmpty() //判断map是否为空
 * </script>
 * ```
 * @return {Object} map 对象<br>
 */

/**
 * 移动端物理回退键监听机制,由于在移动端,android手机的物理回退键和微信浏览器左上角回退按钮的存在,当页面中有弹窗出现时,用户点击了回退键,
 * 默认是回退到了上一个页面,并不是用户想要的关闭弹框,由于这个缺陷的存在,cmp提供一套回退按钮监听机制,使各模块开发处理该问题时
 * 统一处理,并达到,低耦合状态,其机制为:<br>
 *     当进入回退按钮机制时,全部模块或应用需要对回退按钮进行监听时,进入一个堆栈状态,即:先进后出原则,先被放入堆栈中的回退方法,最后被执行,
 *     各模块开发统一在这个堆栈里操作,进出栈由开发者自行控制,各模块开发,只需要把自己的堆栈逻辑处理好,cmp进行统一管理
 *     <ul>
 *         <li>cmp壳端:监听android物理回退键</li>
 *         <li>微信端:监听android物理回退键+微信浏览器左上角自带回退按钮android和ios</li>
 *     </ul>
 * @class backbutton
 */

/**
 * 想要进入回退按钮监听机制,需要调这个函数,兼容了cmp端和微信端
 * @method backbutton
 * @namespace cmp
 * @constructor
 * @example
 * ```
 * <script>
 *     cmp.backbutton();
 * </script>
 * ```
 */

/**
 * 开发者者调用此方法将需要监听回退键执行的函数放入堆栈
 * @method push
 * @namespace cmp
 * @constructor
 * @param {Function} func 需要回退按钮执行的函数
 * @example
 * ```
 * <script>
 *     var closeSelectOrg = function(){//定义关闭弹层的函数
 *          cmp.backbutton.pop(); //关闭函数中要调用弹层出栈函数
 *          //关闭的业务逻辑
 *     }
 *     cmp.backbutton.push(closeSelectOrg);//弹层入栈
 * </script>
 * ```
 */

/**
 * 开发者者调用此方法将需要监听回退键执行的函数取出堆栈,并将这个栈顶函数进行trigger执行<br>
 *     其取出的即为堆栈中的栈顶,一般用在:<br>
 *         如一个弹框,有一个关闭按钮,该关闭按钮的事件绑定就应该将该的主动调用的事件,将堆栈中的栈顶退出,避免已经关闭了该弹框,栈中的函数还存在,导致和其他模块的栈冲突
 * @method pop
 * @namespace cmp
 * @constructor
 * @example
 * ```
 * <script>
 *     cmp.backbutton.pop();
 * </script>
 * ```
 */

/**
 * 工具类<br>
 * @class util
 */

/**
 * 对象合并工具,生成一个新对象
 * @namespace cmp
 * @method extend
 * @param {Object} object1;被合并的对象
 * @param {Object} object2:合并的对象
 * @example
 * ```
 * <script>
 *     cmp.extend({key1:null,key2:"key2default"},{key1:"key1Value",key2:"key2newValue"}) //合并的值为{key1:"key1Value",key2:"key2Value"}
 * </script>
 * ```
 * @returns {Object} 返回一个合并后的新对象
 */

/**
 * uuid 生成器
 * @namespace cmp
 * @method buildUUID
 * @param {Number} [len] 自定义生成的uuid的长度(可以不定义)
 * @example
 * ```
 * <script>
 *     var uuid =  cmp.buildUUID()
 * </script>
 * ```
 * @returns {String} uuid
 */

/**
 * 将timestamps 转为 yyyy-MM-dd hh:mm格式(此方法兼容了时区导致的时间不与中国时间同步的问题)
 * @namespace cmp
 * @method time
 * @param {Number} ms 毫秒值(1970年至今的毫秒数)
 * @param {Boolean} withDate  是否包含日期   不传默认不包含日期
 * @example
 * ```
 * <script>
 *      var formatTime = cmp.time(182738127,true);//2017-03-11
 * </script>
 * ```
 * @returns {String} 日期格式的字符串,如2016-08-31 8:10:10
 */

/**
 * 添加可直接append html字符串的方法
 * @namespace cmp
 * @method append
 * @param {HtmlObject} parent  //父容器
 * @param {String} html  //html字符串(请注意需要传html格式的字符串)
 * @example
 * ```
 * //html
 * <div id="parent"></div><!--父容器-->
 * //js调用
 * <script>
 *     var parent = document.getElementById("parent");
 *     var htmlString = "<div class='cmp-class' style="color:red">被append进行的html</div>"
 *     cmp.append(parent,htmlString)
 * </script>
 *
 * //得到的html如下:
 * <div id="parent">
 *     <div class='cmp-class' style="color:red">被append进行的html</div>
 *</div>
 * ```
 */

/**
 * 在指定的元素的前面添加 html字符串
 * @namespace cmp
 * @method before
 * @param {HtmlObject} target  //指定的html元素
 * @param {String} html  //html字符串(请注意需要传html格式的字符串)
 * @example
 * ```
 * //html
 * <div id="parent">
 *     <div id="target"></div>
 *</div>
 * //js调用
 * <script>
 *     var target = document.getElementById("target");
 *     var htmlString = "<div class='cmp-class' style="color:red">被before进行的html</div>"
 *     cmp.before(target,htmlString)
 * </script>
 *
 * //得到的html如下:
 * <div id="parent">
 *     <div class='cmp-class' style="color:red">被before进行的html</div>
 *     <div id="target"></div>
 *</div>
 * ```
 */

/**
 * 在指定的元素的后面添加html字符串
 * @namespace cmp
 * @method after
 * @param {HtmlObject} target  //指定的html元素
 * @param {String} html  //html字符串(请注意需要传html格式的字符串)
 * @example
 * ```
 * //html
 * <div id="parent">
 *     <div id="target"></div>
 *</div>
 * //js调用
 * <script>
 *     var target = document.getElementById("target");
 *     var htmlString = "<div class='cmp-class' style="color:red">被after进行的html</div>"
 *     cmp.after(target,htmlString)
 * </script>
 *
 * //得到的html如下:
 * <div id="parent">
 *     <div id="target"></div>
 *     <div class='cmp-class' style="color:red">被after进行的html</div>
 *</div>
 * ```
 */

/**
 * 获取指定元素的绝对top值
 * @namespace cmp
 * @method getTop
 * @param {HtmlObject} target  //指定的html元素
 * @example
 * ```
 * <script>
 *     var target = document.getElementById("target");
 *     var top =  cmp.getTop(target)//30
 * </script>
 * ```
 * @returns {Number} 返回元素处于页面中的绝对top值
 */

/**
 * 获取指定元素的绝对left值
 * @namespace cmp
 * @method getLeft
 * @param {HtmlObject} target  //指定的html元素
 * @example
 * ```
 * <script>
 *     var target = document.getElementById("target");
 *     var left = cmp.getLeft(target)//40
 * </script>
 * ```
 * @returns {Number} 返回元素处于页面中的绝对left值
 */

/**
 * 查询指定元素的所有父元素
 * @namespace cmp
 * @method parents
 * @param {HtmlObject} target 指定的html元素
 * @param {String} attr  过滤属性,如果定义了attr参数,则查询指定元素的父元素中有该属性的父元素
 * @example
 * ```
 * <script>
 *     var target = document.getElementById("target");
 *     cmp.parents(target,"binded") //获取所有有binded属性的父元素
 * </script>
 * ```
 */

/**
 * 关闭M3 app,用于Android客户端双击返回按钮提示关闭M3 app
 * @namespace cmp
 * @method closeM3App
 * @example
 * ```
 * <script>
 *     cmp.ready(function(){
 *          cmp.backbutton();  //劫持Android返回按钮事件
 *          cmp.backbutton.push(cmp.closeM3App);  //返回按钮堆栈push关闭M3的函数
 *     });
 * </script>
 * ```
 */

/**
 * 对常用的js原生对象扩展,提供常用的方法,包括:<br>
 *     <ul>
 *         <li>Date对象扩展</li>
 *         <li>String对象扩展</li>
 *         <li>Array对象扩展</li>
 *     </ul>
 * @class ObjectExtension
 */

/**
 * 给Date对象添加格式化函数
 * @namespace cmp
 * @method format
 * @param format 格式化字符串
 * @example
 * ```
 * <script>
 *     var date = new Date();
 *     var formatDate = date.format("yyyy-MM-dd hh:mm:ss")
 *     //formatData = 2012-12-12 12:12:12
 * </script>
 * ```
 * @returns {String} 日期格式化字符串,如2012-12-12
 */

/**
 * String trim方法,替换所有空格,换行符、tab符
 * @namespace cmp
 * @method trim
 * @example
 * ```
 * <script>
 *     var str = "cmp  is a very    goodle   ";
 *     str = str.trim()
 *     //str = cmpisaverygoodle
 * </script>
 * ```
 * @returns {String} 无空格、换行符、tab的字符串
 */


/**
 * 获取该字符串的字符长度,兼容中文(两个字符的情况)
 * @namespace cmp
 * @method getBytesLength
 * @example
 * ```
 * <script>
 *     var str = "cmp  is a very  中国  goodle   ";
 *     var length = str.getBytesLength()
 *     //length = 26
 * </script>
 * ```
 * @returns {Number} 字符串的字符长度
 */

/**
 * 截取字符串的最大长度
 * @namespace cmp
 * @method getLimitLength
 * @param {Number} maxlengh 截取的字符串的最大长度
 * @param {String|Boolean} [symbol] 是否截取完后带上后缀,如:...
 * @example
 * ```
 * <script>
 *     var str = "helloworld";
 *     var nexStr = str.getLimitLength(5,"...");
 *     //nexStr = hello...;
 * </script>
 * ```
 * @returns {String} 截取长度后的字符串
 */

/**
 * 替换字符串中的特殊转义符,以使字符串在html被正确解释
 * @namespace cmp
 * @method escapeHTML
 * @example
 * ```
 * <script>
 *     var str = "helloworld<javascript>alert(\"haha\")</javascript><span>lala</span>&&'\"<br>换个行";
 *     var nexStr = str.escapeHTML();
 *     //nexStr = helloworld&lt;javascript&gt;alert(&#034;haha&#034;)&lt;/javascript&gt;&ltspan;&gt;lala&lt;/span&gt;&amp;&#039;&#034; 换个行
 * </script>
 * ```
 * @returns {String} 无html转义的字符串
 */

/**
 * 判断字符串是否以某个字符开头
 * @namespace cmp
 * @method startsWith
 * @param {String} prefix 前缀字符
 * @example
 * ```
 * <script>
 *     var str = "cmp  is a very  中国  goodle   ";
 *     var result = str.startsWith("c");
 *     //result = true
 * </script>
 * ```
 * @returns {Boolean}
 */

/**
 * 判断字符串是否以某个字符结尾
 * @namespace cmp
 * @method endsWith
 * @param {String} subfix 后缀字符
 * @example
 * ```
 * <script>
 *     var str = "cmp  is a very  中国  goodle   ";
 *     var result = str.endsWith("e")
 *     //result = true
 * </script>
 * ```
 * @returns {Boolean}
 */

/**
 * 判断数组是否有某个item
 * @namespace cmp
 * @method inArray
 * @param {String|Number|Object} item 存在于数组中任何可能的值
 * @example
 * ```
 * <script>
 *     var arr = ["value1","value2"];
 *     var result = arr.inArray("value2");
 *     //result = true
 * </script>
 * ```
 * @returns {Boolean}
 */

/**
 * 删除数组中某个item(前提是保证这个item存在于该数组中)
 * @namespace cmp
 * @method delItem
 * @param {String|Number|Object} item 存在于数组中任何可能的值
 * @example
 * ```
 * <script>
 *     var arr = ["value1","value2"];
 *     var newArr = arr.delItem("value2");
 *     //newArr = ["value1"]
 * </script>
 * ```
 * @returns {Array} 新数组
 */

/**
 * 代理函数注册机制
 * @class funProxy
 */

/**
 * 代理函数设置
 * @namespace cmp.funProxy
 * @method setter
 * @param {String} funName 代理函数名
 * @param {Function|Array} fun 代理函数或者是代理函数数组的集合,定义的代理函数组件会返回三个参数
 * <ul>
 *   <li>data:所传数据</li>
 *   <li>success:成功回调,继续执行下一个代理函数</li>
 *   <li>error:错误回调,终止执行下一个代理函数,整个代理机制完成,并回调开发者定义的错误函数</li>
 * </ul>
 * @example
 * ```
 * <script>
 *    cmp.funProxy.setter("funName",fun);
 * </script>
 * ```
 */

/**
 * 代理函数获取
 * @namespace cmp.funProxy
 * @method getter
 * @param {Objecy} options 配置参数
 *      @param {String} options.funName 事件名称,要求与getter处的名称相同
 *      @param {String} options.data 事件所需业务判断参数
 *      @param {Function} options.success 判断成功后执行的方法(必须执行)
 *      @param {Function} options.error 判断失败后执行的方法(必须执行)
 * @example
 * ```
 * <script>
 *    cmp.funProxy.getter({
 *         funName:"",
 *         data:""
 *         success:function(){
 *            //所有代理函数全部被成功执行后的成功回调
 *         },
 *         error:function(){
 *           //错误终止后的回调(注:只要有一个代理函数未被成功执行,都会回调此错误函数)
 *         }
 *    });
 * </script>
 * ```
 */

/**
 * 复制粘贴板
 * @class pasteboard
 */

/**
 * 复制
 * @namespace cmp
 * @method setString
 * @param {Objecy} [options] 配置参数
 *         @param {String} [options.value] 需要被复制的值
 * @example
 * ```
 * <script>
 *    cmp.pasteboard.setString({
 *         value:"被复制到粘贴板的字符串"
 *    });
 * </script>
 * ```
 */






    
Top